Added options to use sidereal vs solar time, Earth vs Kerbin time, and rounded vs true time.
Added options to use sidereal vs solar time, Earth vs Kerbin time, and rounded vs true time.

file:b/API/Enums.cs (new)
  // VOID © 2015 toadicus
  //
  // This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. To view a
  // copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/
  using System;
 
  namespace VOID
  {
  public enum VOID_TimeScale : UInt32
  {
  KERBIN_TIME = 1, // Earth if 0
  SOLAR_DAY = 4, // Sidereal if 0
  ROUNDED_SCALE = 1024 // Real values if 0
  }
 
  public enum IconState : UInt32
  {
  PowerOff = 1,
  PowerOn = 2,
  Inactive = 4,
  Active = 8
  }
  }
 
 
// VOID // VOID
// //
// IVOID_Module.cs // IVOID_Module.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 System; using System;
   
namespace VOID namespace VOID
{ {
public interface IVOID_Module public interface IVOID_Module
{ {
string Name { get; } string Name { get; }
bool toggleActive { get; set; } bool Active { get; set; }
bool guiRunning { get; } bool GUIRunning { get; }
bool inValidScene { get; } bool InValidScene { get; }
bool inValidGame { get; } bool InValidGame { get; }
   
void DrawGUI(); void DrawGUI();
void StartGUI(); void StartGUI();
void StopGUI(); void StopGUI();
   
void DrawConfigurables(); void DrawConfigurables();
   
void LoadConfig(); void LoadConfig();
   
void _SaveToConfig(KSP.IO.PluginConfiguration config); void Save(KSP.IO.PluginConfiguration config);
} }
   
public interface IVOID_BehaviorModule : IVOID_Module public interface IVOID_BehaviorModule : IVOID_Module
{ {
void Update(); void Update();
void FixedUpdate(); void FixedUpdate();
void OnDestroy(); void OnDestroy();
} }
} }
   
// VOID // VOID
// //
// IVOID_Core.cs // IVOID_Core.cs
// //
// Copyright © 2015, toadicus // Copyright © 2015, 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 KerbalEngineer.VesselSimulator; using KerbalEngineer.VesselSimulator;
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 abstract class VOIDCore : VOID_Module, IVOID_Module public abstract class VOIDCore : VOID_WindowModule, IVOID_Module
{ {
public const double Constant_G = 6.674e-11; public const double Constant_G = 6.674e-11;
public const int CONFIG_VERSION = 2; public const int CONFIG_VERSION = 2;
   
public static bool useToolbarManager; public abstract int ConfigVersion { get; }
   
public abstract int configVersion { get; }  
public virtual bool configNeedsUpdate { get; set; } public virtual bool configNeedsUpdate { get; set; }
   
public abstract int windowID { get; } public abstract int WindowID { get; }
public abstract bool configDirty { get; set; } public abstract bool configDirty { get; set; }
public abstract bool powerAvailable { get; protected set; } public abstract bool powerAvailable { get; protected set; }
   
public abstract List<IVOID_Module> Modules { get; } public abstract IList<IVOID_Module> Modules { get; }
   
public abstract float updateTimer { get; protected set; } public abstract float UpdateTimer { get; protected set; }
public abstract double updatePeriod { get; } public abstract double UpdatePeriod { get; }
   
public virtual float saveTimer { get; protected set; } public virtual float saveTimer { get; protected set; }
   
public abstract GUISkin Skin { get; } public abstract GUISkin Skin { get; }
   
public abstract CelestialBody HomeBody { get; } public abstract CelestialBody HomeBody { get; }
public abstract List<CelestialBody> allBodies { get; } public abstract IList<CelestialBody> AllBodies { get; }
public abstract List<CelestialBody> sortedBodyList { get; protected set; } public abstract List<CelestialBody> SortedBodyList { get; protected set; }
   
public abstract List<VesselType> allVesselTypes { get; } public abstract VesselType[] AllVesselTypes { get; protected set; }
   
public abstract Stage LastStage { get; protected set; } public abstract Stage LastStage { get; protected set; }
public abstract Stage[] Stages { get; protected set; } public abstract Stage[] Stages { get; protected set; }
   
  public abstract VOID_TimeScale TimeScale { get; protected set; }
   
public abstract event VOIDEventHandler onApplicationQuit; public abstract event VOIDEventHandler onApplicationQuit;
public abstract event VOIDEventHandler onSkinChanged; public abstract event VOIDEventHandler onSkinChanged;
   
public virtual void OnGUI() {} public virtual void OnGUI() {}
   
public override void LoadConfig() public override void LoadConfig()
{ {
var config = KSP.IO.PluginConfiguration.CreateForType<VOIDCore>(null);  
   
useToolbarManager = config.GetValue("UseToolbarManager", useToolbarManager);  
   
base.LoadConfig(); base.LoadConfig();
} }
   
public abstract void SaveConfig(); public abstract void SaveConfig();
   
public override void _SaveToConfig(KSP.IO.PluginConfiguration config) public override void Save(KSP.IO.PluginConfiguration config)
{ {
config.SetValue("UseToolbarManager", useToolbarManager); base.Save(config);
   
base._SaveToConfig(config);  
} }
} }
   
public delegate void VOIDEventHandler(object sender); public delegate void VOIDEventHandler(object sender);
} }
   
   
// VOID // VOID
// //
// VOIDMaster.cs // VOIDMaster.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.
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
// Much, much credit to Younata, Adammada, Nivvydaskrl and to all the authors // Much, much credit to Younata, Adammada, Nivvydaskrl and to all the authors
// behind MechJeb, RemoteTech Relay Network, ISA MapSat, and Protractor for some // behind MechJeb, RemoteTech Relay Network, ISA MapSat, and Protractor for some
// invaluable functions and making your nicely written code available to learn from. // invaluable functions and making your nicely written code available to learn from.
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
// This software uses VesselSimulator and Engineer.Extensions from Engineer Redux. // This software uses VesselSimulator and Engineer.Extensions from Engineer Redux.
// Engineer Redux (c) 2013 cybutek // Engineer Redux (c) 2013 cybutek
// Used by permission. // Used by permission.
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
   
using System; using System;
using UnityEngine; using UnityEngine;
using KerbalEngineer.VesselSimulator; using KerbalEngineer.VesselSimulator;
using ToadicusTools; using ToadicusTools;
   
namespace VOID namespace VOID
{ {
public abstract class VOIDMaster<T> : MonoBehaviour public abstract class VOIDMaster<T> : MonoBehaviour
where T : VOIDCore_Generic<T>, new() where T : VOIDCore_Generic<T>, new()
{ {
protected T Core; protected T Core;
   
public abstract void Awake(); public abstract void Awake();
   
public virtual void Update() public virtual void Update()
{ {
if (this.Core != null && !this.InValidScene()) if (this.Core != null && !this.InValidScene())
{ {
this.LogDebug("We have a Core but the scene is not valid for this master. Saving and disposing."); this.LogDebug("We have a Core but the scene is not valid for this master. Saving and disposing.");
   
this.Core.SaveConfig (); this.Core.SaveConfig ();
this.Core.Dispose(); this.Core.Dispose();
this.Core = null; this.Core = null;
return; return;
} }
   
if (this.Core == null && this.InValidScene()) if (this.Core == null && this.InValidScene())
{ {
this.LogDebug("We have no Core and the scene is valid for this master; re-trying Awake."); this.LogDebug("We have no Core and the scene is valid for this master; re-trying Awake.");
this.Awake(); this.Awake();
return; return;
} }
   
this.Core.Update (); this.Core.Update ();
   
if (this.Core.factoryReset) if (this.Core.FactoryReset)
{ {
this.LogDebug("Factory reset is true; deleting config and disposing!"); this.LogDebug("Factory reset is true; deleting config and disposing!");
   
KSP.IO.File.Delete<T>("config.xml"); KSP.IO.File.Delete<T>("config.xml");
this.Core.Dispose(); this.Core.Dispose();
this.Core = null; this.Core = null;
} }
} }
   
public virtual void FixedUpdate() public virtual void FixedUpdate()
{ {
if (this.Core == null) if (this.Core == null)
{ {
return; return;
} }
   
this.Core.FixedUpdate (); this.Core.FixedUpdate ();
} }
   
public virtual void OnGUI() public virtual void OnGUI()
{ {
if (this.Core == null) if (this.Core == null)
{ {
return; return;
} }
   
this.Core.OnGUI(); this.Core.OnGUI();
} }
   
public virtual void OnDestroy() public virtual void OnDestroy()
{ {
if (this.Core == null) if (this.Core == null)
{ {
return; return;
} }
   
this.Core.OnDestroy(); this.Core.OnDestroy();
} }
   
public virtual void OnApplicationQuit() public virtual void OnApplicationQuit()
{ {
if (this.Core == null) if (this.Core == null)
{ {
return; return;
} }
   
this.Core.OnApplicationQuit(); this.Core.OnApplicationQuit();
} }
   
protected virtual bool InValidScene() protected virtual bool InValidScene()
{ {
foreach (var attr in this.GetType().GetCustomAttributes(true)) foreach (var attr in this.GetType().GetCustomAttributes(true))
{ {
if (attr is KSPAddon) if (attr is KSPAddon)
{ {
KSPAddon addonAttr = (KSPAddon)attr; KSPAddon addonAttr = (KSPAddon)attr;
   
switch (addonAttr.startup) switch (addonAttr.startup)
{ {
case KSPAddon.Startup.EveryScene: case KSPAddon.Startup.EveryScene:
return true; return true;
case KSPAddon.Startup.EditorAny: case KSPAddon.Startup.EditorAny:
return HighLogic.LoadedSceneIsEditor; return HighLogic.LoadedSceneIsEditor;
case KSPAddon.Startup.Flight: case KSPAddon.Startup.Flight:
return HighLogic.LoadedSceneIsFlight; return HighLogic.LoadedSceneIsFlight;
case KSPAddon.Startup.MainMenu: case KSPAddon.Startup.MainMenu:
return HighLogic.LoadedScene == GameScenes.MAINMENU; return HighLogic.LoadedScene == GameScenes.MAINMENU;
case KSPAddon.Startup.SpaceCentre: case KSPAddon.Startup.SpaceCentre:
return HighLogic.LoadedScene == GameScenes.SPACECENTER; return HighLogic.LoadedScene == GameScenes.SPACECENTER;
case KSPAddon.Startup.TrackingStation: case KSPAddon.Startup.TrackingStation:
return HighLogic.LoadedScene == GameScenes.TRACKSTATION; return HighLogic.LoadedScene == GameScenes.TRACKSTATION;
default: default:
return false; return false;
} }
} }
} }
   
return false; return false;
} }
} }
} }
   
// VOID // VOID
// //
// VOID_HUDModule.cs // VOID_HUDModule.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 KerbalEngineer.VesselSimulator; using KerbalEngineer.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 abstract class VOID_HUDModule : VOID_Module public abstract class VOID_HUDModule : VOID_Module
{ {
[AVOID_SaveValue("colorIndex")] [AVOID_SaveValue("colorIndex")]
protected VOID_SaveValue<int> _colorIndex; protected VOID_SaveValue<int> _colorIndex;
   
protected List<Color> textColors; protected List<Color> textColors;
   
[AVOID_SaveValue("positionsLocked")] [AVOID_SaveValue("positionsLocked")]
protected VOID_SaveValue<bool> positionsLocked; protected VOID_SaveValue<bool> positionsLocked;
   
public virtual int ColorIndex public virtual 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.value = 0;
return; return;
} }
   
this._colorIndex = value; this._colorIndex.value = value;
} }
} }
   
public virtual List<HUDWindow> Windows public virtual List<HUDWindow> Windows
{ {
get; get;
protected set; protected set;
} }
   
public VOID_HUDModule() : base() public VOID_HUDModule() : base()
{ {
this._colorIndex = 0; this._colorIndex = (VOID_SaveValue<int>)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.positionsLocked = true; this.positionsLocked = (VOID_SaveValue<bool>)true;
   
this.Windows = new List<HUDWindow>(); this.Windows = new List<HUDWindow>();
} }
   
public override void DrawGUI() public override void DrawGUI()
{ {
VOID_Styles.labelHud.normal.textColor = textColors [ColorIndex]; VOID_Styles.labelHud.normal.textColor = textColors [ColorIndex];
   
GUI.skin = this.core.Skin; GUI.skin = this.core.Skin;
   
if (HighLogic.LoadedSceneIsEditor || if (HighLogic.LoadedSceneIsEditor ||
(TimeWarp.WarpMode == TimeWarp.Modes.LOW) || (TimeWarp.CurrentRate <= TimeWarp.MaxPhysicsRate) (TimeWarp.WarpMode == TimeWarp.Modes.LOW) || (TimeWarp.CurrentRate <= TimeWarp.MaxPhysicsRate)
) )
{ {
SimManager.RequestSimulation(); SimManager.RequestSimulation();
} }
   
foreach (HUDWindow window in this.Windows) foreach (HUDWindow window in this.Windows)
{ {
window.WindowPos = GUILayout.Window( window.WindowPos = GUILayout.Window(
this.core.windowID, this.core.WindowID,
window.WindowPos, window.WindowPos,
VOID_Tools.GetWindowHandler(window.WindowFunction), VOID_Tools.GetWindowHandler(window.WindowFunction),
GUIContent.none, GUIContent.none,
GUIStyle.none GUIStyle.none
); );
} }
} }
   
public override void DrawConfigurables() public override void DrawConfigurables()
{ {
base.DrawConfigurables(); base.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)))
{ {
foreach (HUDWindow window in this.Windows) foreach (HUDWindow window in this.Windows)
{ {
window.WindowPos = new Rect(window.defaultWindowPos); window.WindowPos = new Rect(window.defaultWindowPos);
} }
} }
   
this.positionsLocked = GUITools.Toggle(this.positionsLocked, "Lock HUD Positions"); this.positionsLocked.value = GUITools.Toggle(this.positionsLocked, "Lock HUD Positions");
} }
   
public override void LoadConfig() public override void LoadConfig()
{ {
base.LoadConfig(); base.LoadConfig();
   
var config = KSP.IO.PluginConfiguration.CreateForType<VOID_HUDModule>(); var config = KSP.IO.PluginConfiguration.CreateForType<VOID_HUDModule>();
config.load(); config.load();
   
foreach (HUDWindow window in this.Windows) foreach (HUDWindow window in this.Windows)
{ {
string saveName = string.Format("{0}_{1}", this.GetType().Name, window.WindowName); string saveName = string.Format("{0}_{1}", this.GetType().Name, window.WindowName);
Rect loadedPos = config.GetValue(saveName, window.defaultWindowPos); Rect loadedPos = config.GetValue(saveName, window.defaultWindowPos);
   
window.WindowPos = loadedPos; window.WindowPos = loadedPos;
} }
} }
   
public override void _SaveToConfig(KSP.IO.PluginConfiguration config) public override void Save(KSP.IO.PluginConfiguration config)
{ {
base._SaveToConfig(config); base.Save(config);
   
foreach (HUDWindow window in this.Windows) foreach (HUDWindow window in this.Windows)
{ {
string saveName = string.Format("{0}_{1}", this.GetType().Name, window.WindowName); string saveName = string.Format("{0}_{1}", this.GetType().Name, window.WindowName);
config.SetValue(saveName, window.WindowPos); config.SetValue(saveName, window.WindowPos);
} }
} }
} }
   
public class HUDWindow public class HUDWindow
{ {
public readonly Rect defaultWindowPos; public readonly Rect defaultWindowPos;
   
private Rect _windowPos; private Rect _windowPos;
   
public Action<int> WindowFunction public Action<int> WindowFunction
{ {
get; get;
private set; private set;
} }
   
public Rect WindowPos public Rect WindowPos
{ {
get get
{ {
return this._windowPos; return this._windowPos;
} }
set set
{ {
if (value != this._windowPos) if (value != this._windowPos)
{ {
this._windowPos = value; this._windowPos = value;
   
if (VOID_Data.Core != null) if (VOID_Data.Core != null)
{ {
VOID_Data.Core.configDirty = true; VOID_Data.Core.configDirty = true;
} }
} }
} }
} }
   
public string WindowName public string WindowName
{ {
get; get;
private set; private set;
} }
   
private HUDWindow() {} private HUDWindow() {}
   
public HUDWindow(string name, Action<int> windowFunc, Rect defaultPos) public HUDWindow(string name, Action<int> windowFunc, Rect defaultPos)
{ {
this.WindowName = name; this.WindowName = name;
this.WindowFunction = windowFunc; this.WindowFunction = windowFunc;
this.defaultWindowPos = defaultPos; this.defaultWindowPos = defaultPos;
this.WindowPos = new Rect(this.defaultWindowPos); this.WindowPos = new Rect(this.defaultWindowPos);
} }
} }
} }
   
   
// VOID // VOID
// //
// VOID_Module.cs // VOID_Module.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 System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using ToadicusTools; using ToadicusTools;
using UnityEngine; using UnityEngine;
   
namespace VOID namespace VOID
{ {
public abstract class VOID_Module : IVOID_Module public abstract class VOID_Module : IVOID_Module
{ {
/* /*
* Fields * Fields
* */ * */
[AVOID_SaveValue("Active")] [AVOID_SaveValue("Active")]
protected VOID_SaveValue<bool> _Active = false; protected VOID_SaveValue<bool> active = (VOID_SaveValue<bool>)false;
   
  protected float lastUpdate = 0;
   
private GameScenes[] validScenes; private GameScenes[] validScenes;
private Game.Modes[] validModes; private Game.Modes[] validModes;
   
protected float lastUpdate = 0;  
   
/* /*
* Properties * Properties
* */ * */
protected virtual VOIDCore core  
{ public virtual bool Active
get {
{ get
return VOID_Data.Core; {
} return this.active && this.InValidGame && this.InValidScene;
}  
   
protected virtual bool timeToUpdate  
{  
get  
{  
return (  
(this.core.updateTimer - this.lastUpdate) > this.core.updatePeriod ||  
this.lastUpdate > this.core.updateTimer  
);  
}  
}  
   
public virtual bool toggleActive  
{  
get  
{  
return this._Active && this.inValidGame && this.inValidScene;  
} }
set set
{ {
this._Active = value && this.inValidGame && this.inValidScene; this.active.value = value && this.InValidGame && this.InValidScene;
} }
} }
   
public virtual bool guiRunning public virtual bool GUIRunning
{ {
get get
{ {
if ( if (
RenderingManager.fetch == null || RenderingManager.fetch == null ||
RenderingManager.fetch.postDrawQueue == null || RenderingManager.fetch.postDrawQueue == null ||
RenderingManager.fetch.postDrawQueue.Length < 4 RenderingManager.fetch.postDrawQueue.Length < 4
) )
{ {
return false; return false;
} }
else else
{ {
Delegate callback = RenderingManager.fetch.postDrawQueue[3]; Delegate callback = RenderingManager.fetch.postDrawQueue[3];
if (callback == null) if (callback == null)
{ {
return false; return false;
} }
   
return callback.GetInvocationList().Contains((Callback)this.DrawGUI); return callback.GetInvocationList().Contains((Callback)this.DrawGUI);
} }
} }
} }
   
public virtual GameScenes[] ValidScenes public virtual bool InValidGame
{ {
get get
{ {
if (this.validScenes == null) return this.ValidModes.Contains(HighLogic.CurrentGame.Mode);
{ }
Tools.PostDebugMessage(this, "validScenes is null when checking inValidScene; fetching attribute."); }
foreach (var attr in this.GetType().GetCustomAttributes(false))  
{ public virtual bool InValidScene
if (attr is VOID_ScenesAttribute)  
{  
VOID_ScenesAttribute addonAttr = (VOID_ScenesAttribute)attr;  
   
this.validScenes = addonAttr.ValidScenes;  
   
Tools.PostDebugMessage("Found VOID_ScenesAttribute; validScenes set.");  
   
break;  
}  
}  
   
if (this.validScenes == null)  
{  
this.validScenes = new GameScenes[] { GameScenes.FLIGHT };  
Tools.PostDebugMessage("No VOID_ScenesAttribute found; validScenes defaulted to flight.");  
}  
}  
   
return this.validScenes;  
}  
}  
   
public virtual bool inValidScene  
{ {
get get
{ {
return this.ValidScenes.Contains(HighLogic.LoadedScene); return this.ValidScenes.Contains(HighLogic.LoadedScene);
} }
  }
   
  public virtual string Name
  {
  get;
  protected set;
} }
   
public virtual Game.Modes[] ValidModes public virtual Game.Modes[] ValidModes
{ {
get get
{ {
if (this.validModes == null) if (this.validModes == null)
{ {
Tools.PostDebugMessage(this, "validModes is null when checking inValidGame; fetching attribute."); Tools.PostDebugMessage(this, "validModes is null when checking inValidGame; fetching attribute.");
foreach (var attr in this.GetType().GetCustomAttributes(false)) foreach (var attr in this.GetType().GetCustomAttributes(false))
{ {
if (attr is VOID_GameModesAttribute) if (attr is VOID_GameModesAttribute)
{ {
VOID_GameModesAttribute addonAttr = (VOID_GameModesAttribute)attr; VOID_GameModesAttribute addonAttr = (VOID_GameModesAttribute)attr;
   
this.validModes = addonAttr.ValidModes; this.validModes = addonAttr.ValidModes;
   
Tools.PostDebugMessage("Found VOID_GameModesAttribute; validScenes set."); Tools.PostDebugMessage("Found VOID_GameModesAttribute; validScenes set.");
   
break; break;
} }
} }
   
if (this.validModes == null) if (this.validModes == null)
{ {
this.validModes = new Game.Modes[] this.validModes = new Game.Modes[]
{ {
Game.Modes.CAREER, Game.Modes.CAREER,
Game.Modes.SANDBOX, Game.Modes.SANDBOX,
Game.Modes.SCENARIO, Game.Modes.SCENARIO,
Game.Modes.SCENARIO_NON_RESUMABLE, Game.Modes.SCENARIO_NON_RESUMABLE,
Game.Modes.SCIENCE_SANDBOX Game.Modes.SCIENCE_SANDBOX
}; };
   
Tools.PostDebugMessage("No VOID_GameModesAttribute found; validScenes defaulted to flight."); Tools.PostDebugMessage("No VOID_GameModesAttribute found; validScenes defaulted to flight.");
} }
} }
   
return this.validModes; return this.validModes;
} }
} }
   
public virtual bool inValidGame public virtual GameScenes[] ValidScenes
{ {
get get
{ {
return this.ValidModes.Contains(HighLogic.CurrentGame.Mode); if (this.validScenes == null)
} {
} Tools.PostDebugMessage(this, "validScenes is null when checking inValidScene; fetching attribute.");
  foreach (var attr in this.GetType().GetCustomAttributes(false))
public virtual string Name {
{ if (attr is VOID_ScenesAttribute)
get; {
protected set; VOID_ScenesAttribute addonAttr = (VOID_ScenesAttribute)attr;
}  
  this.validScenes = addonAttr.ValidScenes;
public virtual Vessel vessel  
  Tools.PostDebugMessage("Found VOID_ScenesAttribute; validScenes set.");
   
  break;
  }
  }
   
  if (this.validScenes == null)
  {
  this.validScenes = new GameScenes[] { GameScenes.FLIGHT };
  Tools.PostDebugMessage("No VOID_ScenesAttribute found; validScenes defaulted to flight.");
  }
  }
   
  return this.validScenes;
  }
  }
   
  public virtual Vessel Vessel
{ {
get get
{ {
return FlightGlobals.ActiveVessel; return FlightGlobals.ActiveVessel;
  }
  }
   
  protected virtual VOIDCore core
  {
  get
  {
  return VOID_Data.Core;
  }
  }
   
  protected virtual bool timeToUpdate
  {
  get
  {
  return (
  (this.core.UpdateTimer - this.lastUpdate) > this.core.UpdatePeriod ||
  this.lastUpdate > this.core.UpdateTimer
  );
} }
} }
   
/* /*
* Methods * Methods
* */ * */
public void StartGUI() public virtual void StartGUI()
{ {
if (!this.toggleActive || this.guiRunning) if (!this.Active || this.GUIRunning)
{ {
return; return;
} }
   
Tools.PostDebugMessage (string.Format("Adding {0} to the draw queue.", this.GetType().Name)); Tools.PostDebugMessage (string.Format("Adding {0} to the draw queue.", this.GetType().Name));
RenderingManager.AddToPostDrawQueue (3, this.DrawGUI); RenderingManager.AddToPostDrawQueue (3, this.DrawGUI);
} }
   
public void StopGUI() public virtual void StopGUI()
{ {
if (!this.guiRunning) if (!this.GUIRunning)
{ {
return; return;
} }
Tools.PostDebugMessage (string.Format("Removing {0} from the draw queue.", this.GetType().Name)); Tools.PostDebugMessage (string.Format("Removing {0} from the draw queue.", this.GetType().Name));
RenderingManager.RemoveFromPostDrawQueue (3, this.DrawGUI); RenderingManager.RemoveFromPostDrawQueue (3, this.DrawGUI);
} }
   
public abstract void DrawGUI(); public abstract void DrawGUI();
   
public virtual void DrawConfigurables() {} public virtual void DrawConfigurables() {}
   
public virtual void LoadConfig() public virtual void LoadConfig()
{ {
var config = KSP.IO.PluginConfiguration.CreateForType<VOID_Module> (); var config = KSP.IO.PluginConfiguration.CreateForType<VOID_Module> ();
config.load (); config.load ();
   
if (this is VOIDCore) if (this is VOIDCore)
{ {
int configVersion = config.GetValue("VOID_Core_configValue", 2); int configVersion = config.GetValue("VOID_Core_configValue", 2);
   
if (configVersion < VOIDCore.CONFIG_VERSION) if (configVersion < VOIDCore.CONFIG_VERSION)
{ {
((VOIDCore)this).configNeedsUpdate = true; ((VOIDCore)this).configNeedsUpdate = true;
} }
} }
   
foreach (var field in this.GetType().GetMembers( foreach (var field in this.GetType().GetMembers(
BindingFlags.NonPublic | BindingFlags.NonPublic |
BindingFlags.Public | BindingFlags.Public |
BindingFlags.Instance | BindingFlags.Instance |
BindingFlags.FlattenHierarchy BindingFlags.FlattenHierarchy
)) ))
{ {
if (!(field is FieldInfo || field is PropertyInfo)) if (!(field is FieldInfo || field is PropertyInfo))
{ {
continue; continue;
} }
   
if (field is PropertyInfo && (field as PropertyInfo).GetIndexParameters().Length > 0) if (field is PropertyInfo && (field as PropertyInfo).GetIndexParameters().Length > 0)
{ {
continue; continue;
} }
   
object[] attrs = field.GetCustomAttributes(typeof(AVOID_SaveValue), false); object[] attrs = field.GetCustomAttributes(typeof(AVOID_SaveValue), false);
   
if (attrs.Length == 0) { if (attrs.Length == 0) {
continue; continue;
} }
   
AVOID_SaveValue attr = attrs.FirstOrDefault () as AVOID_SaveValue; AVOID_SaveValue attr = attrs.FirstOrDefault () as AVOID_SaveValue;
   
string fieldName = string.Empty; string fieldName = string.Empty;
   
if (this is VOIDCore || this.core.configNeedsUpdate) if (this is VOIDCore || this.core.configNeedsUpdate)
{ {
string typeName = this.GetType().Name;; string typeName = this.GetType().Name;;
   
if (this is VOIDCore && ((VOIDCore)this).configNeedsUpdate) if (this is VOIDCore && ((VOIDCore)this).configNeedsUpdate)
{ {
if (this is VOIDCore_Flight) if (this is VOIDCore_Flight)
{ {
typeName = "VOID_Core"; typeName = "VOID_Core";
} }
else if (this is VOIDCore_Editor) else if (this is VOIDCore_Editor)
{ {
typeName = "VOID_EditorCore"; typeName = "VOID_EditorCore";
} }
} }
   
fieldName = string.Format("{0}_{1}", typeName, attr.Name); fieldName = string.Format("{0}_{1}", typeName, attr.Name);
} }
else else
{ {
fieldName = string.Format( fieldName = string.Format(
"{0}_{1}_{2}", "{0}_{1}_{2}",
this.GetType().Name, this.GetType().Name,
Enum.GetName(typeof(GameScenes), HighLogic.LoadedScene), Enum.GetName(typeof(GameScenes), HighLogic.LoadedScene),
attr.Name attr.Name
); );
} }
   
Tools.PostDebugMessage(string.Format("{0}: Loading field {1}.", this.GetType().Name, fieldName)); Tools.PostDebugMessage(string.Format("{0}: Loading field {1}.", this.GetType().Name, fieldName));
   
object fieldValue; object fieldValue;
   
if (field is FieldInfo) if (field is FieldInfo)
{ {
fieldValue = (field as FieldInfo).GetValue(this); fieldValue = (field as FieldInfo).GetValue(this);
} }
else else
{ {
fieldValue = (field as PropertyInfo).GetValue(this, null); fieldValue = (field as PropertyInfo).GetValue(this, null);
} }
   
bool convertBack = false; bool convertBack = false;
if (fieldValue is IVOID_SaveValue) if (fieldValue is IVOID_SaveValue)
{ {
fieldValue = (fieldValue as IVOID_SaveValue).value; fieldValue = (fieldValue as IVOID_SaveValue).value;
convertBack = true; convertBack = true;
} }
   
fieldValue = config.GetValue(fieldName, fieldValue); fieldValue = config.GetValue(fieldName, fieldValue);
   
if (convertBack) if (convertBack)
{ {
Type type = typeof(VOID_SaveValue<>).MakeGenericType (fieldValue.GetType ()); Type type = typeof(VOID_SaveValue<>).MakeGenericType (fieldValue.GetType ());
IVOID_SaveValue convertValue = Activator.CreateInstance (type) as IVOID_SaveValue; IVOID_SaveValue convertValue = Activator.CreateInstance (type) as IVOID_SaveValue;
convertValue.SetValue (fieldValue); convertValue.SetValue (fieldValue);
fieldValue = convertValue; fieldValue = convertValue;
} }
   
if (field is FieldInfo) if (field is FieldInfo)
{ {
(field as FieldInfo).SetValue(this, fieldValue); (field as FieldInfo).SetValue(this, fieldValue);
} }
else else
{ {
(field as PropertyInfo).SetValue(this, fieldValue, null); (field as PropertyInfo).SetValue(this, fieldValue, null);
} }
   
Tools.PostDebugMessage(string.Format("{0}: Loaded field {1}.", this.GetType().Name, fieldName)); Tools.PostDebugMessage(string.Format("{0}: Loaded field {1}.", this.GetType().Name, fieldName));
} }
} }
   
public virtual void _SaveToConfig(KSP.IO.PluginConfiguration config) public virtual void Save(KSP.IO.PluginConfiguration config)
{ {
foreach (var field in this.GetType().GetMembers( foreach (var field in this.GetType().GetMembers(
BindingFlags.Instance | BindingFlags.Instance |
BindingFlags.NonPublic | BindingFlags.NonPublic |
BindingFlags.Public | BindingFlags.Public |
BindingFlags.FlattenHierarchy BindingFlags.FlattenHierarchy
)) ))
{ {
object[] attrs = field.GetCustomAttributes(typeof(AVOID_SaveValue), false); object[] attrs = field.GetCustomAttributes(typeof(AVOID_SaveValue), false);
   
if (attrs.Length == 0) { if (attrs.Length == 0) {
continue; continue;
} }
   
AVOID_SaveValue attr = attrs.FirstOrDefault () as AVOID_SaveValue; AVOID_SaveValue attr = attrs.FirstOrDefault () as AVOID_SaveValue;
   
string fieldName; string fieldName;
   
if (this is VOIDCore) if (this is VOIDCore)
{ {
fieldName = string.Format("{0}_{1}", this.GetType().Name, attr.Name); fieldName = string.Format("{0}_{1}", this.GetType().Name, attr.Name);
} }
else else
{ {
fieldName = string.Format( fieldName = string.Format(
"{0}_{1}_{2}", "{0}_{1}_{2}",
this.GetType().Name, this.GetType().Name,
Enum.GetName(typeof(GameScenes), HighLogic.LoadedScene), Enum.GetName(typeof(GameScenes), HighLogic.LoadedScene),
attr.Name attr.Name
); );
} }
   
object fieldValue; object fieldValue;
   
if (field is FieldInfo) if (field is FieldInfo)
{ {
fieldValue = (field as FieldInfo).GetValue(this); fieldValue = (field as FieldInfo).GetValue(this);
} }
else else
{ {
fieldValue = (field as PropertyInfo).GetValue(this, null); fieldValue = (field as PropertyInfo).GetValue(this, null);
} }
   
if (fieldValue is IVOID_SaveValue) if (fieldValue is IVOID_SaveValue)
{ {
fieldValue = (fieldValue as IVOID_SaveValue).value; fieldValue = (fieldValue as IVOID_SaveValue).value;
} }
   
config.SetValue(fieldName, fieldValue); config.SetValue(fieldName, fieldValue);
   
Tools.PostDebugMessage(string.Format("{0}: Saved field {1}.", this.GetType().Name, fieldName)); Tools.PostDebugMessage(string.Format("{0}: Saved field {1}.", this.GetType().Name, fieldName));
} }
} }
} }
   
public abstract class VOID_WindowModule : VOID_Module public abstract class VOID_WindowModule : VOID_Module
{ {
protected static GUIContent closeButton;  
   
protected static Dictionary<int, Action<int>> DecoratedWindows;  
   
[AVOID_SaveValue("WindowPos")] [AVOID_SaveValue("WindowPos")]
protected Rect WindowPos; protected Rect WindowPos;
protected float defWidth; protected float defWidth;
protected float defHeight; protected float defHeight;
   
  protected bool decorateWindow;
   
protected string inputLockName; protected string inputLockName;
   
protected virtual Action<int> DecoratedWindow  
{  
get  
{  
return VOID_WindowModule.DecorateWindow(  
this.ModuleWindow,  
this.WindowPos,  
(bool active) => { this.toggleActive = active; }  
);  
}  
}  
   
public VOID_WindowModule() : base() public VOID_WindowModule() : base()
{ {
this.defWidth = 250f; this.defWidth = 250f;
this.defHeight = 50f; this.defHeight = 50f;
   
  this.decorateWindow = true;
   
this.inputLockName = string.Concat(this.Name, "_edlock"); this.inputLockName = string.Concat(this.Name, "_edlock");
   
this.WindowPos = new Rect(Screen.width / 2, Screen.height / 2, this.defWidth, this.defHeight); this.WindowPos = new Rect(Screen.width / 2, Screen.height / 2, this.defWidth, this.defHeight);
} }
   
public abstract void ModuleWindow(int _); public virtual void ModuleWindow(int id)
  {
  GUIStyle buttonStyle = this.core.Skin.button;
  RectOffset padding = buttonStyle.padding;
  RectOffset border = buttonStyle.border;
   
  Rect closeRect = new Rect(
  0f,
  0f,
  border.left + border.right,
  border.top + border.bottom
  );
   
  closeRect.width = Mathf.Max(closeRect.width, 16f);
  closeRect.height = Mathf.Max(closeRect.height, 16f);
   
  closeRect.x = this.WindowPos.width - closeRect.width - 2f;
  closeRect.y = 2f;
   
  GUI.Button(closeRect, GUIContent.none, buttonStyle);
   
  if (Event.current.type == EventType.repaint && Input.GetMouseButtonUp(0))
  {
  if (closeRect.Contains(Event.current.mousePosition))
  {
  this.Active = false;
  this.removeUILock();
  }
  }
   
  GUI.DragWindow();
  }
   
public override void DrawGUI() public override void DrawGUI()
{ {
GUI.skin = this.core.Skin; GUI.skin = this.core.Skin;
   
Rect _Pos = this.WindowPos; Rect _Pos = this.WindowPos;
   
_Pos = GUILayout.Window( _Pos = GUILayout.Window(
this.core.windowID, this.core.WindowID,
_Pos, _Pos,
VOID_Tools.GetWindowHandler(this.DecoratedWindow), VOID_Tools.GetWindowHandler(this.ModuleWindow),
this.Name, this.Name,
GUILayout.Width(this.defWidth), GUILayout.Width(this.defWidth),
GUILayout.Height(this.defHeight), GUILayout.Height(this.defHeight)
GUILayout.ExpandWidth(true),  
GUILayout.ExpandHeight(true)  
); );
   
bool cursorInWindow = _Pos.Contains(Mouse.screenPos); bool cursorInWindow = _Pos.Contains(Mouse.screenPos);
   
  if (cursorInWindow)
  {
  this.setUILock();
  }
  else
  {
  this.removeUILock();
  }
   
  if (HighLogic.LoadedSceneIsEditor)
  {
  _Pos = Tools.ClampRectToEditorPad(_Pos);
  }
  else
  {
  _Pos = Tools.ClampRectToScreen(_Pos);
  }
   
  if (_Pos != this.WindowPos)
  {
  this.WindowPos = _Pos;
  this.core.configDirty = true;
  }
  }
   
  protected void setUILock()
  {
switch (HighLogic.LoadedScene) switch (HighLogic.LoadedScene)
{ {
case GameScenes.EDITOR: case GameScenes.EDITOR:
if (cursorInWindow) InputLockManager.SetControlLock(
{ ControlTypes.EDITOR_ICON_HOVER | ControlTypes.EDITOR_ICON_PICK |
InputLockManager.SetControlLock( ControlTypes.EDITOR_PAD_PICK_COPY | ControlTypes.EDITOR_PAD_PICK_COPY,
ControlTypes.EDITOR_ICON_HOVER | ControlTypes.EDITOR_ICON_PICK | this.inputLockName
ControlTypes.EDITOR_PAD_PICK_COPY | ControlTypes.EDITOR_PAD_PICK_COPY, );
this.inputLockName EditorLogic.fetch.Lock(false, false, false, this.inputLockName);
);  
EditorLogic.fetch.Lock(false, false, false, this.inputLockName);  
}  
else  
{  
EditorLogic.fetch.Unlock(this.inputLockName);  
}  
break; break;
case GameScenes.FLIGHT: case GameScenes.FLIGHT:
if (cursorInWindow) InputLockManager.SetControlLock(ControlTypes.CAMERACONTROLS, this.inputLockName);
{  
InputLockManager.SetControlLock(ControlTypes.CAMERACONTROLS, this.inputLockName);  
}  
else if (InputLockManager.GetControlLock(this.inputLockName) != ControlTypes.None)  
{  
InputLockManager.RemoveControlLock(this.inputLockName);  
}  
break; break;
case GameScenes.SPACECENTER: case GameScenes.SPACECENTER:
if (cursorInWindow) InputLockManager.SetControlLock(
{ ControlTypes.KSC_FACILITIES | ControlTypes.CAMERACONTROLS,
InputLockManager.SetControlLock( this.inputLockName
ControlTypes.KSC_FACILITIES | ControlTypes.CAMERACONTROLS, );
this.inputLockName  
);  
}  
else if (InputLockManager.GetControlLock(this.inputLockName) != ControlTypes.None)  
{  
InputLockManager.RemoveControlLock(this.inputLockName);  
}  
break; break;
} }
  }
if (HighLogic.LoadedSceneIsEditor)  
{ protected void removeUILock()
_Pos = Tools.ClampRectToEditorPad(_Pos); {
} switch (HighLogic.LoadedScene)
else {
{ case GameScenes.EDITOR:
_Pos = Tools.ClampRectToScreen(_Pos); EditorLogic.fetch.Unlock(this.inputLockName);
} break;
  case GameScenes.FLIGHT:
if (_Pos != this.WindowPos) InputLockManager.RemoveControlLock(this.inputLockName);
{ break;
this.WindowPos = _Pos; case GameScenes.SPACECENTER:
this.core.configDirty = true; InputLockManager.RemoveControlLock(this.inputLockName);
} break;
}  
   
public static Action<int> DecorateWindow(Action<int> func, Rect windowRect, Callback<bool> callBack)  
{  
if (DecoratedWindows == null)  
{  
DecoratedWindows = new Dictionary<int, Action<int>>();  
}  
   
int hashCode = func.GetHashCode();  
   
if (!DecoratedWindows.ContainsKey(hashCode))  
{  
DecoratedWindows[hashCode] = delegate(int id)  
{  
func(id);  
   
if (closeButton == null)  
{  
closeButton = new GUIContent("X");  
}  
   
Rect closeRect = GUILayoutUtility.GetRect(  
closeButton,  
VOID_Data.Core.Skin.button,  
GUILayout.ExpandWidth(false)  
);  
   
closeRect.x = windowRect.width - closeRect.width - VOID_Data.Core.Skin.button.margin.right;  
closeRect.y = VOID_Data.Core.Skin.button.margin.top;  
   
GUI.Button(closeRect, closeButton, VOID_Data.Core.Skin.button);  
   
if (Event.current.type == EventType.repaint && Input.GetMouseButtonUp(0))  
{  
if (closeRect.Contains(Event.current.mousePosition))  
{  
callBack(false);  
}  
}  
};  
}  
   
return DecoratedWindows[hashCode];  
}  
   
public static void UncacheWindow(Action<int> func)  
{  
if (DecoratedWindows != null)  
{  
int hashCode = func.GetHashCode();  
   
if (DecoratedWindows.ContainsKey(hashCode))  
{  
VOID_Tools.UncacheWindow(DecoratedWindows[hashCode]);  
   
DecoratedWindows.Remove(hashCode);  
}  
} }
} }
} }
} }
   
   
  // VOID
  //
  // VOID_SingletonModule.cs
  //
  // Copyright © 2015, toadicus
  // All rights reserved.
  //
  // Redistribution and use in source and binary forms, with or without modification,
  // are permitted provided that the following conditions are met:
  //
  // 1. Redistributions of source code must retain the above copyright notice,
  // this list of conditions and the following disclaimer.
  //
  // 2. Redistributions in binary form must reproduce the above copyright notice,
  // this list of conditions and the following disclaimer in the documentation and/or other
  // materials provided with the distribution.
  //
  // 3. Neither the name of the copyright holder nor the names of its contributors may be used
  // to endorse or promote products derived from this software without specific prior written permission.
  //
  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  using System;
 
  namespace VOID
  {
  public abstract class VOID_SingletonCore<T> : VOIDCore, IVOID_Module, IDisposable
  where T : VOID_Module, new()
  {
  #region Singleton Members
  /*
  * Static Members
  * */
  protected static bool _initialized = false;
 
  public static bool Initialized
  {
  get
  {
  return _initialized;
  }
  }
 
  protected static T _instance;
 
  public static T Instance
  {
  get
  {
  if (_instance == null)
  {
  _instance = new T();
  _initialized = true;
  }
  return _instance;
  }
  }
 
  public abstract void Dispose();
  #endregion
  }
  }
 
 
// VOID  
//  
// VOID_SingletonModule.cs  
//  
// Copyright © 2015, toadicus  
// All rights reserved.  
//  
// Redistribution and use in source and binary forms, with or without modification,  
// are permitted provided that the following conditions are met:  
//  
// 1. Redistributions of source code must retain the above copyright notice,  
// this list of conditions and the following disclaimer.  
//  
// 2. Redistributions in binary form must reproduce the above copyright notice,  
// this list of conditions and the following disclaimer in the documentation and/or other  
// materials provided with the distribution.  
//  
// 3. Neither the name of the copyright holder nor the names of its contributors may be used  
// to endorse or promote products derived from this software without specific prior written permission.  
//  
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,  
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE  
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,  
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR  
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE  
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
using System;  
 
namespace VOID  
{  
public abstract class VOID_SingletonModule<T> : VOIDCore, IVOID_Module  
where T : VOID_Module, new()  
{  
#region Singleton Members  
/*  
* Static Members  
* */  
protected static bool _initialized = false;  
 
public static bool Initialized  
{  
get  
{  
return _initialized;  
}  
}  
 
protected static T _instance;  
 
public static T Instance  
{  
get  
{  
if (_instance == null)  
{  
_instance = new T();  
_initialized = true;  
}  
return _instance;  
}  
}  
#endregion  
}  
}  
 
 
  // VOID
  //
  // VOID_SingletonModule.cs
  //
  // Copyright © 2015, toadicus
  // All rights reserved.
  //
  // Redistribution and use in source and binary forms, with or without modification,
  // are permitted provided that the following conditions are met:
  //
  // 1. Redistributions of source code must retain the above copyright notice,
  // this list of conditions and the following disclaimer.
  //
  // 2. Redistributions in binary form must reproduce the above copyright notice,
  // this list of conditions and the following disclaimer in the documentation and/or other
  // materials provided with the distribution.
  //
  // 3. Neither the name of the copyright holder nor the names of its contributors may be used
  // to endorse or promote products derived from this software without specific prior written permission.
  //
  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  using System;
 
  namespace VOID
  {
  public abstract class VOID_SingletonWindow<T> : VOID_WindowModule, IVOID_Module, IDisposable
  where T : VOID_WindowModule, new()
  {
  #region Singleton Members
  /*
  * Static Members
  * */
  protected static bool _initialized = false;
 
  public static bool Initialized
  {
  get
  {
  return _initialized;
  }
  }
 
  protected static T _instance;
 
  public static T Instance
  {
  get
  {
  if (_instance == null)
  {
  _instance = new T();
  _initialized = true;
  }
  return _instance;
  }
  }
 
  public virtual void Dispose()
  {
  _instance = null;
  _initialized = false;
  }
  #endregion
  }
  }
 
 
// VOID // VOID
// //
// AssemblyInfo.cs // AssemblyInfo.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 System.Reflection; using System.Reflection;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
   
[assembly: KSPAssemblyDependency("ToadicusTools", 0, 0)] [assembly: KSPAssemblyDependency("ToadicusTools", 0, 0)]
[assembly: KSPAssemblyDependency("VesselSimulator", 0, 0)] [assembly: KSPAssemblyDependency("VesselSimulator", 0, 0)]
   
// Information about this assembly is defined by the following attributes. // Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project. // Change them to the values specific to your project.
[assembly: AssemblyTitle("VOID")] [assembly: AssemblyTitle("VOID")]
[assembly: AssemblyDescription("A KSP mod that provides at-a-glance information about Vessels, Orbits, and their states.")] [assembly: AssemblyDescription("A KSP mod that provides at-a-glance information about Vessels, Orbits, and their states.")]
[assembly: AssemblyCopyright("toadicus")] [assembly: AssemblyCopyright("toadicus")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision, // The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision. // and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion("0.16.4.*")] [assembly: AssemblyVersion("0.17.*")]
// The following attributes are used to specify the signing key for the assembly, // The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing. // if desired. See the Mono documentation for more information about signing.
//[assembly: AssemblyDelaySign(false)] //[assembly: AssemblyDelaySign(false)]
//[assembly: AssemblyKeyFile("")] //[assembly: AssemblyKeyFile("")]
   
   
// VOID // VOID
// //
// VOID_DataValue.cs // VOID_DataValue.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 System; using System;
using ToadicusTools; using ToadicusTools;
using UnityEngine; using UnityEngine;
   
namespace VOID namespace VOID
{ {
public class VOID_DataValue<T> : IVOID_DataValue public class VOID_DataValue<T> : IVOID_DataValue
{ {
/* /*
* Static Members * Static Members
* */ * */
public static implicit operator T(VOID_DataValue<T> v) public static implicit operator T(VOID_DataValue<T> v)
{ {
return (T)v.Value; return (T)v.Value;
} }
   
/* /*
* Instance Members * Instance Members
* */ * */
/* /*
* Fields * Fields
* */ * */
protected T cache; protected T cache;
protected Func<T> ValueFunc; protected Func<T> ValueFunc;
protected float lastUpdate; protected float lastUpdate;
   
/* /*
* Properties * Properties
* */ * */
public string Label { get; protected set; } public string Label { get; protected set; }
public string Units { get; protected set; } public string Units { get; protected set; }
   
object IVOID_DataValue.Value object IVOID_DataValue.Value
{ {
get get
{ {
return this.Value; return this.Value;
} }
} }
   
public T Value public T Value
{ {
get get
{ {
if ( if (
(VOID_Data.Core.updateTimer - this.lastUpdate > VOID_Data.Core.updatePeriod) || (VOID_Data.Core.UpdateTimer - this.lastUpdate > VOID_Data.Core.UpdatePeriod) ||
(this.lastUpdate > VOID_Data.Core.updateTimer) (this.lastUpdate > VOID_Data.Core.UpdateTimer)
) )
{ {
this.Refresh(); this.Refresh();
} }
return (T)this.cache; return (T)this.cache;
} }
} }
   
/* /*
* Methods * Methods
* */ * */
public VOID_DataValue(string Label, Func<T> ValueFunc, string Units = "") public VOID_DataValue(string Label, Func<T> ValueFunc, string Units = "")
{ {
this.Label = Label; this.Label = Label;
this.Units = Units; this.Units = Units;
this.ValueFunc = ValueFunc; this.ValueFunc = ValueFunc;
this.lastUpdate = 0; this.lastUpdate = 0;
   
VOID_Data.DataValues[this.GetHashCode()] = this; VOID_Data.DataValues[this.GetHashCode()] = this;
} }
   
public void Refresh() public void Refresh()
{ {
this.cache = this.ValueFunc.Invoke (); this.cache = this.ValueFunc.Invoke ();
this.lastUpdate = VOID_Data.Core.updateTimer; this.lastUpdate = VOID_Data.Core.UpdateTimer;
} }
   
public T GetFreshValue() public T GetFreshValue()
{ {
this.Refresh (); this.Refresh ();
return (T)this.cache; return (T)this.cache;
} }
   
public virtual string ValueUnitString() { public virtual string ValueUnitString() {
return this.Value.ToString() + this.Units; return this.Value.ToString() + this.Units;
} }
   
public virtual void DoGUIHorizontal() public virtual void DoGUIHorizontal()
{ {
GUILayout.BeginHorizontal (GUILayout.ExpandWidth (true)); GUILayout.BeginHorizontal (GUILayout.ExpandWidth (true));
GUILayout.Label (this.Label + ":"); GUILayout.Label (this.Label + ":");
GUILayout.FlexibleSpace (); GUILayout.FlexibleSpace ();
GUILayout.Label (this.ValueUnitString(), GUILayout.ExpandWidth (false)); GUILayout.Label (this.ValueUnitString(), GUILayout.ExpandWidth (false));
GUILayout.EndHorizontal (); GUILayout.EndHorizontal ();
} }
   
public override int GetHashCode() public override int GetHashCode()
{ {
int hash; int hash;
unchecked unchecked
{ {
hash = 79999; hash = 79999;
   
hash = hash * 104399 + this.Label.GetHashCode(); hash = hash * 104399 + this.Label.GetHashCode();
hash = hash * 104399 + this.ValueFunc.GetHashCode(); hash = hash * 104399 + this.ValueFunc.GetHashCode();
hash = hash * 104399 + this.Units.GetHashCode(); hash = hash * 104399 + this.Units.GetHashCode();
} }
   
return hash; return hash;
} }
   
public override string ToString() public override string ToString()
{ {
return string.Format ( return string.Format (
"{0}: {1}{2}", "{0}: {1}{2}",
this.Label, this.Label,
this.Value.ToString (), this.Value.ToString (),
this.Units this.Units
); );
} }
} }
   
public abstract class VOID_NumValue<T> : VOID_DataValue<T>, IFormattable public abstract class VOID_NumValue<T> : VOID_DataValue<T>, IFormattable
where T : IFormattable, IConvertible, IComparable where T : IFormattable, IConvertible, IComparable
{ {
public static IFormatProvider formatProvider = Tools.SIFormatter; public static IFormatProvider formatProvider = Tools.SIFormatter;
   
public static implicit operator Double(VOID_NumValue<T> v) public static implicit operator Double(VOID_NumValue<T> v)
{ {
return v.ToDouble(); return v.ToDouble();
} }
   
public static implicit operator Int32(VOID_NumValue<T> v) public static implicit operator Int32(VOID_NumValue<T> v)
{ {
return v.ToInt32(); return v.ToInt32();
} }
   
public static implicit operator Single(VOID_NumValue<T> v) public static implicit operator Single(VOID_NumValue<T> v)
{ {
return v.ToSingle(); return v.ToSingle();
} }
   
public VOID_NumValue(string Label, Func<T> ValueFunc, string Units = "") : base(Label, ValueFunc, Units) public VOID_NumValue(string Label, Func<T> ValueFunc, string Units = "") : base(Label, ValueFunc, Units)
{ {
   
} }
   
public virtual double ToDouble(IFormatProvider provider) public virtual double ToDouble(IFormatProvider provider)
{ {
return this.Value.ToDouble(provider); return this.Value.ToDouble(provider);
} }
   
public virtual double ToDouble() public virtual double ToDouble()
{ {
return this.ToDouble(formatProvider); return this.ToDouble(formatProvider);
} }
   
public virtual int ToInt32(IFormatProvider provider) public virtual int ToInt32(IFormatProvider provider)
{ {
return this.Value.ToInt32(provider); return this.Value.ToInt32(provider);
} }
   
public virtual int ToInt32() public virtual int ToInt32()
{ {
return this.ToInt32(formatProvider); return this.ToInt32(formatProvider);
} }
   
public virtual float ToSingle(IFormatProvider provider) public virtual float ToSingle(IFormatProvider provider)
{ {
return this.Value.ToSingle(provider); return this.Value.ToSingle(provider);
} }
   
public virtual float ToSingle() public virtual float ToSingle()
{ {
return this.ToSingle(formatProvider); return this.ToSingle(formatProvider);
} }
   
public virtual string ToString(string format) public virtual string ToString(string format)
{ {
return this.ToString(format, formatProvider); return this.ToString(format, formatProvider);
} }
   
public virtual string ToString(string format, IFormatProvider provider) public virtual string ToString(string format, IFormatProvider provider)
{ {
return string.Format ( return string.Format (
"{0}{1}", "{0}{1}",
this.Value.ToString(format, provider), this.Value.ToString(format, provider),
this.Units this.Units
); );
} }
   
public virtual string ToSIString(int digits = 3, int MinMagnitude = 0, int MaxMagnitude = int.MaxValue) public virtual string ToSIString(int digits = 3, int MinMagnitude = 0, int MaxMagnitude = int.MaxValue)
{ {
return string.Format ( return string.Format (
"{0}{1}", "{0}{1}",
Tools.MuMech_ToSI (this, digits, MinMagnitude, MaxMagnitude), Tools.MuMech_ToSI (this, digits, MinMagnitude, MaxMagnitude),
this.Units this.Units
); );
} }
   
public virtual string ValueUnitString(string format) public virtual string ValueUnitString(string format)
{ {
return this.Value.ToString(format, formatProvider) + this.Units; return this.Value.ToString(format, formatProvider) + this.Units;
} }
public virtual string ValueUnitString(int digits) { public virtual string ValueUnitString(int digits) {
return Tools.MuMech_ToSI(this, digits) + this.Units; return string.Format("{0}{1}", SIFormatProvider.ToSI(this, digits), Units);
} }
   
public virtual string ValueUnitString(int digits, int MinMagnitude, int MaxMagnitude) public virtual string ValueUnitString(int digits, int MinMagnitude, int MaxMagnitude)
{ {
return Tools.MuMech_ToSI(this, digits, MinMagnitude, MaxMagnitude) + this.Units; return Tools.MuMech_ToSI(this, digits, MinMagnitude, MaxMagnitude) + this.Units;
} }
   
public virtual void DoGUIHorizontal(string format) public virtual void DoGUIHorizontal(string format)
{ {
GUILayout.BeginHorizontal (GUILayout.ExpandWidth (true)); GUILayout.BeginHorizontal (GUILayout.ExpandWidth (true));
GUILayout.Label (this.Label + ":"); GUILayout.Label (this.Label + ":");
GUILayout.FlexibleSpace (); GUILayout.FlexibleSpace ();
GUILayout.Label (this.ValueUnitString(format), GUILayout.ExpandWidth (false)); GUILayout.Label (this.ValueUnitString(format), GUILayout.ExpandWidth (false));
GUILayout.EndHorizontal (); GUILayout.EndHorizontal ();
} }
   
public virtual int DoGUIHorizontal(int digits, bool precisionButton = true) public virtual int DoGUIHorizontal(int digits, bool precisionButton = true)
{ {
if (precisionButton) if (precisionButton)
{ {
return this.DoGUIHorizontalPrec(digits); return this.DoGUIHorizontalPrec(digits);
} }
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label(this.Label + ":", GUILayout.ExpandWidth(true)); GUILayout.Label(this.Label + ":", GUILayout.ExpandWidth(true));
GUILayout.FlexibleSpace(); GUILayout.FlexibleSpace();
GUILayout.Label(this.ValueUnitString(digits), GUILayout.ExpandWidth(false)); GUILayout.Label(this.ValueUnitString(digits), GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
return digits; return digits;
} }
   
public virtual int DoGUIHorizontalPrec(int digits) public virtual int DoGUIHorizontalPrec(int digits)
{ {
double magnitude; if (digits < 0 || digits > 8)
double magLimit; {
  digits = 5;
magnitude = Math.Log10(Math.Abs((double)this)); }
   
magLimit = Math.Max(Math.Abs(magnitude), 3d) + 3d;  
magLimit = Math.Round(Math.Ceiling(magLimit / 3f)) * 3d;  
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label(this.Label + "ⁱ:", GUILayout.ExpandWidth(true)); GUILayout.Label(this.Label + "ⁱ:", GUILayout.ExpandWidth(true));
GUILayout.FlexibleSpace(); GUILayout.FlexibleSpace();
   
if (magnitude >= 0) GUILayout.Label(this.ValueUnitString(digits), GUILayout.ExpandWidth(false));
{  
GUILayout.Label(this.ValueUnitString(3, int.MinValue, (int)magnitude - digits), GUILayout.ExpandWidth(false));  
}  
else  
{  
GUILayout.Label(this.ValueUnitString(3, (int)magnitude + digits, int.MaxValue), GUILayout.ExpandWidth(false));  
}  
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
if (Event.current.type == EventType.mouseUp) if (Event.current.type == EventType.mouseUp)
{ {
Rect lastRect = GUILayoutUtility.GetLastRect(); Rect lastRect = GUILayoutUtility.GetLastRect();
if (lastRect.Contains(Event.current.mousePosition)) if (lastRect.Contains(Event.current.mousePosition))
{ {
Tools.PostDebugMessage(string.Format("{0}: Changing digits from {1} within magLimit {2}.", Tools.PostDebugMessage(string.Format("{0}: Changing digits from {1}",
this.GetType().Name, this.GetType().Name,
digits, digits
magLimit)); ));
   
if (Event.current.button == 0) if (Event.current.button == 0)
{ {
digits = (digits + 3) % (int)magLimit; digits = (digits + 3) % 9;
} }
else if (Event.current.button == 1) else if (Event.current.button == 1)
{ {
digits = (digits - 3) % (int)magLimit; digits = (digits - 3) % 9;
} }
   
if (digits < 0) if (digits < 0)
{ {
digits += (int)magLimit; digits += 9;
} }
   
Tools.PostDebugMessage(string.Format("{0}: Changed digits to {1}." + Tools.PostDebugMessage(string.Format("{0}: Changed digits to {1}.",
"\n\tNew minMagnitude: {2}, maxMagnitude: {3}" +  
"\n\tMagnitude: {4}",  
this.GetType().Name, this.GetType().Name,
digits, digits
magnitude >= 0 ? int.MinValue : (int)magnitude - 4 + digits,  
magnitude >= 0 ? (int)magnitude - digits : int.MaxValue,  
magnitude  
)); ));
} }
} }
   
return digits; return digits;
} }
} }
   
public class VOID_DoubleValue : VOID_NumValue<double> public class VOID_DoubleValue : VOID_NumValue<double>
{ {
public VOID_DoubleValue(string Label, Func<double> ValueFunc, string Units) : base(Label, ValueFunc, Units) {} public VOID_DoubleValue(string Label, Func<double> ValueFunc, string Units) : base(Label, ValueFunc, Units) {}
} }
   
public class VOID_FloatValue : VOID_NumValue<float> public class VOID_FloatValue : VOID_NumValue<float>
{ {
public VOID_FloatValue(string Label, Func<float> ValueFunc, string Units) : base(Label, ValueFunc, Units) {} public VOID_FloatValue(string Label, Func<float> ValueFunc, string Units) : base(Label, ValueFunc, Units) {}
} }
   
public class VOID_IntValue : VOID_NumValue<int> public class VOID_IntValue : VOID_NumValue<int>
{ {
public VOID_IntValue(string Label, Func<int> ValueFunc, string Units) : base(Label, ValueFunc, Units) {} public VOID_IntValue(string Label, Func<int> ValueFunc, string Units) : base(Label, ValueFunc, Units) {}
} }
   
public class VOID_StrValue : VOID_DataValue<string> public class VOID_StrValue : VOID_DataValue<string>
{ {
public VOID_StrValue(string Label, Func<string> ValueFunc) : base(Label, ValueFunc, "") {} public VOID_StrValue(string Label, Func<string> ValueFunc) : base(Label, ValueFunc, "") {}
} }
   
public class VOID_Vector3dValue : VOID_DataValue<Vector3d> public class VOID_Vector3dValue : VOID_DataValue<Vector3d>
{ {
public VOID_Vector3dValue(string Label, Func<Vector3d> ValueFunc, string Units) public VOID_Vector3dValue(string Label, Func<Vector3d> ValueFunc, string Units)
: base(Label, ValueFunc, Units) : base(Label, ValueFunc, Units)
{} {}
   
public string ToString(string format) public string ToString(string format)
{ {
return string.Format("{0}: {1}{2}", return string.Format("{0}: {1}{2}",
this.Label, this.Label,
this.Value.ToString(format), this.Value.ToString(format),
this.Units this.Units
); );
} }
   
public string ValueUnitString(string format) { public string ValueUnitString(string format) {
return this.Value.ToString(format) + this.Units; return this.Value.ToString(format) + this.Units;
} }
} }
} }
   
   
  // VOID
  //
  // VOID_Localization.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.
 
  public static class VOID_Localization
  {
  public static string void_primary = "Primary";
  public static string void_altitude_asl = "Altitude (ASL)";
  public static string void_velocity = "Velocity";
  public static string void_apoapsis = "Apoapsis";
  public static string void_periapsis = "Periapsis";
  }
// VOID // VOID
// //
// VOID_SaveValue.cs // VOID_SaveValue.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.Collections.Generic; using System.Collections.Generic;
using ToadicusTools; using ToadicusTools;
using UnityEngine; using UnityEngine;
   
namespace VOID namespace VOID
{ {
public struct VOID_SaveValue<T> : IVOID_SaveValue public struct VOID_SaveValue<T> : IVOID_SaveValue
{ {
private T _value; private T _value;
private Type _type; private Type _type;
   
private VOIDCore Core private VOIDCore Core
{ {
get get
{ {
return VOID_Data.Core; return VOID_Data.Core;
} }
} }
   
object IVOID_SaveValue.value object IVOID_SaveValue.value
{ {
get get
{ {
return this.value; return this.value;
} }
} }
   
public T value public T value
{ {
get get
{ {
return this._value; return this._value;
} }
set set
{ {
if (this.Core != null && !System.Object.Equals(this._value, value)) if (this.Core != null && !System.Object.Equals(this._value, value))
{ {
Tools.PostDebugMessage (string.Format ( Tools.PostDebugMessage (string.Format (
"VOID: Dirtying config for type {0} in method {1}." + "VOID: Dirtying config for type {0}." +
"\n\t Old Value: {2}, New Value: {3}" + "\n\t Old Value: {2}, New Value: {3}" +
"\n\t Object.Equals(New, Old): {4}", "\n\t Object.Equals(New, Old): {4}\n" +
  "{1}",
this._type, this._type,
new System.Diagnostics.StackTrace().GetFrame(1).GetMethod(), new System.Diagnostics.StackTrace().ToString(),
this._value, this._value,
value, value,
System.Object.Equals(this._value, value) System.Object.Equals(this._value, value)
)); ));
this.Core.configDirty = true; this.Core.configDirty = true;
} }
this._value = value; this._value = value;
} }
} }
   
public Type type public Type type
{ {
get get
{ {
if (this._type == null && this._value != null) if (this._type == null && this._value != null)
{ {
this._type = this._value.GetType (); this._type = this._value.GetType ();
} }
return this._type; return this._type;
} }
set set
{ {
this._type = value; this._type = value;
} }
} }
   
public void SetValue(object v) public void SetValue(object v)
{ {
this.value = (T)v; this.value = (T)v;
} }
   
public static implicit operator T(VOID_SaveValue<T> v) public static implicit operator T(VOID_SaveValue<T> v)
{ {
return (T)v.value; return (T)v.value;
} }
   
public static implicit operator VOID_SaveValue<T>(T v) public static explicit operator VOID_SaveValue<T>(T v)
{ {
VOID_SaveValue<T> r = new VOID_SaveValue<T>(); VOID_SaveValue<T> r = new VOID_SaveValue<T>();
r.type = v.GetType(); r.type = v.GetType();
r.value = v; r.value = v;
   
return r; return r;
} }
   
public override string ToString() public override string ToString()
{ {
return this.value.ToString(); return this.value.ToString();
} }
} }
} }
   
   
  // VOID © 2015 toadicus
  //
  // This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. To view a
  // copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/
 
  using KerbalEngineer.VesselSimulator;
  using KSP;
  using System;
  using System.Collections.Generic;
  using UnityEngine;
 
  namespace VOID
  {
  public static class VOID_StageExtensions
  {
  public static double NominalThrust(this Stage stage)
  {
  if (stage.actualThrust == 0d)
  {
  return stage.thrust;
  }
  else
  {
  return stage.actualThrust;
  }
  }
 
  public static double MassFlow(this Stage stage)
  {
  double stageIsp = VOID_Data.Core.LastStage.isp;
  double stageThrust = stage.NominalThrust();
 
  return stageThrust / (stageIsp * VOID_Data.KerbinGee);
  }
  }
  }
 
 
// VOID // VOID
// //
// VOID_Tools.cs // VOID_Tools.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.Collections.Generic; using System.Collections.Generic;
using ToadicusTools; using ToadicusTools;
using UnityEngine; using UnityEngine;
   
namespace VOID namespace VOID
{ {
public static class VOID_Tools public static class VOID_Tools
{ {
#region CelestialBody Utilities #region CelestialBody Utilities
public static bool hasAncestor(this CelestialBody bodyA, CelestialBody bodyB) public static bool hasAncestor(this CelestialBody bodyA, CelestialBody bodyB)
{ {
if (bodyA == null || bodyB == null) if (bodyA == null || bodyB == null)
{ {
return false; return false;
} }
   
while (bodyA.orbitDriver != null) while (bodyA.orbitDriver != null)
{ {
if (bodyA.orbit.referenceBody == bodyB) if (bodyA.orbit.referenceBody == bodyB)
{ {
return true; return true;
} }
   
bodyA = bodyA.orbit.referenceBody; bodyA = bodyA.orbit.referenceBody;
} }
   
return false; return false;
} }
   
public static bool NearestRelatedParents(ref CelestialBody bodyA, ref CelestialBody bodyB) public static bool NearestRelatedParents(ref CelestialBody bodyA, ref CelestialBody bodyB)
{ {
if (bodyA == null || bodyB == null || bodyA.orbitDriver == null || bodyB.orbitDriver == null) if (bodyA == null || bodyB == null || bodyA.orbitDriver == null || bodyB.orbitDriver == null)
{ {
throw new ArgumentException(string.Concat( throw new ArgumentException(string.Concat(
"CelestialBody::FindRelatedParents: ", "CelestialBody::FindRelatedParents: ",
"Neither body may be null, and both bodies must have orbits." "Neither body may be null, and both bodies must have orbits."
)); ));
} }
   
CelestialBody a, b; CelestialBody a, b;
   
a = bodyA; a = bodyA;
   
while (bodyA.orbitDriver != null) while (bodyA.orbitDriver != null)
{ {
b = bodyB; b = bodyB;
   
while (b.orbitDriver != null) while (b.orbitDriver != null)
{ {
if (a.orbit.referenceBody == b.orbit.referenceBody) if (a.orbit.referenceBody == b.orbit.referenceBody)
{ {
bodyA = a; bodyA = a;
bodyB = b; bodyB = b;
return true; return true;
} }
   
b = b.orbit.referenceBody; b = b.orbit.referenceBody;
} }
   
a = a.orbit.referenceBody; a = a.orbit.referenceBody;
} }
   
return false; return false;
} }
#endregion #endregion
   
#region VESSEL_EXTENSIONS_SCIENCE #region VESSEL_EXTENSIONS_SCIENCE
public static CBAttributeMapSO.MapAttribute GetBiome(this Vessel vessel) public static CBAttributeMapSO.MapAttribute GetBiome(this Vessel vessel)
{ {
CBAttributeMapSO.MapAttribute mapAttribute; CBAttributeMapSO.MapAttribute mapAttribute;
   
try try
{ {
CBAttributeMapSO BiomeMap = vessel.mainBody.BiomeMap; CBAttributeMapSO BiomeMap = vessel.mainBody.BiomeMap;
   
double lat = vessel.latitude * Math.PI / 180d; double lat = vessel.latitude * Math.PI / 180d;
double lon = vessel.longitude * Math.PI / 180d; double lon = vessel.longitude * Math.PI / 180d;
   
mapAttribute = BiomeMap.GetAtt(lat, lon); mapAttribute = BiomeMap.GetAtt(lat, lon);
   
/* /*
lon -= Math.PI / 2d; lon -= Math.PI / 2d;
   
if (lon < 0d) if (lon < 0d)
{ {
lon += 2d * Math.PI; lon += 2d * Math.PI;
} }
   
float v = (float)(lat / Math.PI) + 0.5f; float v = (float)(lat / Math.PI) + 0.5f;
float u = (float)(lon / (2d * Math.PI)); float u = (float)(lon / (2d * Math.PI));
   
Color pixelBilinear = BiomeMap.Map.GetPixelBilinear(u, v); Color pixelBilinear = BiomeMap.Map.GetPixelBilinear(u, v);
mapAttribute = BiomeMap.defaultAttribute; mapAttribute = BiomeMap.defaultAttribute;
   
if (BiomeMap.Map != null) if (BiomeMap.Map != null)
{ {
if (BiomeMap.exactSearch) if (BiomeMap.exactSearch)
{ {
for (int i = 0; i < BiomeMap.Attributes.Length; ++i) for (int i = 0; i < BiomeMap.Attributes.Length; ++i)
{ {
if (pixelBilinear == BiomeMap.Attributes[i].mapColor) if (pixelBilinear == BiomeMap.Attributes[i].mapColor)
{ {
mapAttribute = BiomeMap.Attributes[i]; mapAttribute = BiomeMap.Attributes[i];
} }
} }
} }
else else
{ {
float zero = 0; float zero = 0;
float num = 1 / zero; float num = 1 / zero;
for (int j = 0; j < BiomeMap.Attributes.Length; ++j) for (int j = 0; j < BiomeMap.Attributes.Length; ++j)
{ {
Color mapColor = BiomeMap.Attributes[j].mapColor; Color mapColor = BiomeMap.Attributes[j].mapColor;
float sqrMagnitude = ((Vector4)(mapColor - pixelBilinear)).sqrMagnitude; float sqrMagnitude = ((Vector4)(mapColor - pixelBilinear)).sqrMagnitude;
if (sqrMagnitude < num) if (sqrMagnitude < num)
{ {
bool testCase = true; bool testCase = true;
if (BiomeMap.nonExactThreshold != -1) if (BiomeMap.nonExactThreshold != -1)
{ {
testCase = (sqrMagnitude < BiomeMap.nonExactThreshold); testCase = (sqrMagnitude < BiomeMap.nonExactThreshold);
} }
if (testCase) if (testCase)
{ {
mapAttribute = BiomeMap.Attributes[j]; mapAttribute = BiomeMap.Attributes[j];
num = sqrMagnitude; num = sqrMagnitude;
} }
} }
} }
} }
} }
*/ */
} }
catch (NullReferenceException) catch (NullReferenceException)
{ {
mapAttribute = new CBAttributeMapSO.MapAttribute(); mapAttribute = new CBAttributeMapSO.MapAttribute();
mapAttribute.name = "N/A"; mapAttribute.name = "N/A";
} }
   
return mapAttribute; return mapAttribute;
} }
   
public static ExperimentSituations GetExperimentSituation(this Vessel vessel) public static ExperimentSituations GetExperimentSituation(this Vessel vessel)
{ {
if (vessel == null) if (vessel == null)
{ {
return ExperimentSituations.SrfSplashed; return ExperimentSituations.SrfSplashed;
} }
   
Vessel.Situations situation = vessel.situation; Vessel.Situations situation = vessel.situation;
   
switch (situation) switch (situation)
{ {
case Vessel.Situations.PRELAUNCH: case Vessel.Situations.PRELAUNCH:
case Vessel.Situations.LANDED: case Vessel.Situations.LANDED:
return ExperimentSituations.SrfLanded; return ExperimentSituations.SrfLanded;
case Vessel.Situations.SPLASHED: case Vessel.Situations.SPLASHED:
return ExperimentSituations.SrfSplashed; return ExperimentSituations.SrfSplashed;
case Vessel.Situations.FLYING: case Vessel.Situations.FLYING:
if (vessel.altitude < (double)vessel.mainBody.scienceValues.flyingAltitudeThreshold) if (vessel.altitude < (double)vessel.mainBody.scienceValues.flyingAltitudeThreshold)
{ {
return ExperimentSituations.FlyingLow; return ExperimentSituations.FlyingLow;
} }
else else
{ {
return ExperimentSituations.FlyingHigh; return ExperimentSituations.FlyingHigh;
} }
} }
   
if (vessel.altitude < (double)vessel.mainBody.scienceValues.spaceAltitudeThreshold) if (vessel.altitude < (double)vessel.mainBody.scienceValues.spaceAltitudeThreshold)
{ {
return ExperimentSituations.InSpaceLow; return ExperimentSituations.InSpaceLow;
} }
else else
{ {
return ExperimentSituations.InSpaceHigh; return ExperimentSituations.InSpaceHigh;
} }
} }
   
public static string HumanString(this ExperimentSituations situation) public static string HumanString(this ExperimentSituations situation)
{ {
switch (situation) switch (situation)
{ {
case ExperimentSituations.FlyingHigh: case ExperimentSituations.FlyingHigh:
return "Upper Atmosphere"; return "Upper Atmosphere";
case ExperimentSituations.FlyingLow: case ExperimentSituations.FlyingLow:
return "Flying"; return "Flying";
case ExperimentSituations.SrfLanded: case ExperimentSituations.SrfLanded:
return "Surface"; return "Surface";
case ExperimentSituations.InSpaceLow: case ExperimentSituations.InSpaceLow:
return "Near in Space"; return "Near in Space";
case ExperimentSituations.InSpaceHigh: case ExperimentSituations.InSpaceHigh:
return "High in Space"; return "High in Space";
case ExperimentSituations.SrfSplashed: case ExperimentSituations.SrfSplashed:
return "Splashed Down"; return "Splashed Down";
default: default:
return "Unknown"; return "Unknown";
} }
} }
#endregion #endregion
   
#region VESSEL_EXTENSIONS_LAT_LONG #region VESSEL_EXTENSIONS_LAT_LONG
public static string GetLongitudeString(this Vessel vessel, string format = "F4") public static string GetLongitudeString(this Vessel vessel, string format = "F4")
{ {
string dir_long = "W"; string dir_long = "W";
double v_long = vessel.longitude; double v_long = vessel.longitude;
   
v_long = FixDegreeDomain(v_long); v_long = FixDegreeDomain(v_long);
   
if (v_long < -180d) if (v_long < -180d)
{ {
v_long += 360d; v_long += 360d;
} }
if (v_long >= 180) if (v_long >= 180)
{ {
v_long -= 360d; v_long -= 360d;
} }
   
if (v_long > 0) if (v_long > 0)
dir_long = "E"; dir_long = "E";
   
return string.Format("{0}° {1}", Math.Abs(v_long).ToString(format), dir_long); return string.Format("{0}° {1}", Math.Abs(v_long).ToString(format), dir_long);
} }
   
public static string GetLatitudeString(this Vessel vessel, string format = "F4") public static string GetLatitudeString(this Vessel vessel, string format = "F4")
{ {
string dir_lat = "S"; string dir_lat = "S";
double v_lat = vessel.latitude; double v_lat = vessel.latitude;
if (v_lat > 0) if (v_lat > 0)
dir_lat = "N"; dir_lat = "N";
   
return string.Format("{0}° {1}", Math.Abs(v_lat).ToString(format), dir_lat); return string.Format("{0}° {1}", Math.Abs(v_lat).ToString(format), dir_lat);
} }
#endregion #endregion
   
#region VESSEL_EXTENSIONS_GENERAL #region VESSEL_EXTENSIONS_GENERAL
public static double TrueAltitude(Vessel vessel) public static double TrueAltitude(Vessel vessel)
{ {
double trueAltitude = vessel.orbit.altitude - vessel.terrainAltitude; double trueAltitude = vessel.orbit.altitude - vessel.terrainAltitude;
   
// HACK: This assumes that on worlds with oceans, all water is fixed at 0 m, // HACK: This assumes that on worlds with oceans, all water is fixed at 0 m,
// and water covers the whole surface at 0 m. // and water covers the whole surface at 0 m.
if (vessel.terrainAltitude < 0 && vessel.mainBody.ocean) if (vessel.terrainAltitude < 0 && vessel.mainBody.ocean)
{ {
trueAltitude = vessel.orbit.altitude; trueAltitude = vessel.orbit.altitude;
} }
   
return trueAltitude; return trueAltitude;
} }
   
public static double Radius(this Vessel vessel) public static double Radius(this Vessel vessel)
{ {
double radius; double radius;
   
radius = vessel.altitude; radius = vessel.altitude;
   
if (vessel.mainBody != null) if (vessel.mainBody != null)
{ {
radius += vessel.mainBody.Radius; radius += vessel.mainBody.Radius;
} }
   
return radius; return radius;
} }
#endregion #endregion
   
#region GEOMETRY_UTILS #region GEOMETRY_UTILS
public static double FixAngleDomain(double Angle, bool Degrees = false) public static double FixAngleDomain(double Angle, bool Degrees = false)
{ {
double Extent = 2d * Math.PI; double Extent = 2d * Math.PI;
if (Degrees) if (Degrees)
{ {
Extent = 360d; Extent = 360d;
} }
   
Angle = Angle % (Extent); Angle = Angle % (Extent);
if (Angle < 0d) if (Angle < 0d)
{ {
Angle += Extent; Angle += Extent;
} }
   
return Angle; return Angle;
} }
   
public static double FixDegreeDomain(double Angle) public static double FixDegreeDomain(double Angle)
{ {
return FixAngleDomain(Angle, true); return FixAngleDomain(Angle, true);
} }
#endregion #endregion
   
  #region WINDOW_UTILS
private static Dictionary<int, GUI.WindowFunction> functionCache; private static Dictionary<int, GUI.WindowFunction> functionCache;
public static UnityEngine.GUI.WindowFunction GetWindowHandler(Action<int> func) public static UnityEngine.GUI.WindowFunction GetWindowHandler(Action<int> func)
{ {
if (functionCache == null) if (functionCache == null)
{ {
functionCache = new Dictionary<int, GUI.WindowFunction>(); functionCache = new Dictionary<int, GUI.WindowFunction>();
} }
   
int hashCode = func.GetHashCode(); int hashCode = func.GetHashCode();
   
if (!functionCache.ContainsKey(hashCode)) if (!functionCache.ContainsKey(hashCode))
{ {
functionCache[hashCode] = delegate (int id) functionCache[hashCode] = delegate (int id)
{ {
try try
{ {
func(id); func(id);
} }
#if DEBUG #if DEBUG
catch (ArgumentException) catch (ArgumentException)
#else #else
catch (ArgumentException) catch (ArgumentException)
#endif #endif
{ {
Debug.LogWarning( Debug.LogWarning(
string.Format("[{0}]: ArgumentException caught during window call. This is not a bug.", string.Format("[{0}]: ArgumentException caught during window call. This is not a bug.",
func.Target.GetType().Name func.Target.GetType().Name
)); ));
   
/*#if DEBUG /*#if DEBUG
Debug.LogException(ex); Debug.LogException(ex);
#endif*/ #endif*/
} }
catch (Exception ex) catch (Exception ex)
{ {
Debug.LogError( Debug.LogError(
string.Format("[{0}]: {1} caught during window call.\nMessage:\n{2}\nStackTrace:\n{3}", string.Format("[{0}]: {1} caught during window call.\nMessage:\n{2}\nStackTrace:\n{3}",
func.Target.GetType().Name, func.Target.GetType().Name,
ex.GetType().Name, ex.GetType().Name,
ex.Message, ex.Message,
ex.StackTrace ex.StackTrace
)); ));
} }
}; };
} }
   
return functionCache[hashCode]; return functionCache[hashCode];
} }
   
public static void UncacheWindow(Action<int> func) public static void UncacheWindow(Action<int> func)
{ {
if (functionCache != null) if (functionCache != null)
{ {
int hashCode = func.GetHashCode(); int hashCode = func.GetHashCode();
   
if (functionCache.ContainsKey(hashCode)) if (functionCache.ContainsKey(hashCode))
{ {
functionCache.Remove(hashCode); functionCache.Remove(hashCode);
} }
} }
} }
  #endregion
   
  #region TIME_UTILS
/// <summary> /// <summary>
/// Formats the interval given in seconds as a human-friendly /// Formats the interval given in seconds as a human-friendly
/// time period in [[[[years, ]days, ]hours, ]minutes, and ]seconds. /// time period in [[[[years, ]days, ]hours, ]minutes, and ]seconds.
/// ///
/// Uses sidereal days, since "6 hours per day" is the Kerbal standard. /// Uses sidereal days, since "6 hours per day" is the Kerbal standard.
/// </summary> /// </summary>
/// <returns>Human readable interval</returns> /// <returns>Human readable interval</returns>
/// <param name="seconds"></param> /// <param name="seconds"></param>
public static string FormatInterval(double seconds) public static string FormatInterval(double seconds)
{ {
return UnpackedTime.FromSeconds(seconds).FormatAsSpan(); return UnpackedTime.FromSeconds(seconds).FormatAsSpan();
} }
   
/// <summary> /// <summary>
/// Formats the date given in seconds since epoch as a human-friendly /// Formats the date given in seconds since epoch as a human-friendly
/// date in the format YY, DD, HH:MM:SS /// date in the format YY, DD, HH:MM:SS
/// </summary> /// </summary>
/// <returns>The date.</returns> /// <returns>The date.</returns>
/// <param name="seconds">Seconds.</param> /// <param name="seconds">Seconds.</param>
public static string FormatDate(double seconds) public static string FormatDate(double seconds)
{ {
return UnpackedTime.FromSeconds(seconds).FormatAsDate(); return UnpackedTime.FromSeconds(seconds).FormatAsDate();
} }
   
public class UnpackedTime public class UnpackedTime
{ {
public const double SecondsPerMinute = 60d; public const double SecondsPerMinute = 60d;
public const double SecondsPerHour = 3600d; public const double SecondsPerHour = 3600d;
   
public static double SecondsPerDay public static double SecondsPerDay
{ {
get get
{ {
if (GameSettings.KERBIN_TIME) VOID_TimeScale flags = VOID_Data.Core.TimeScale &
  (VOID_TimeScale.KERBIN_TIME | VOID_TimeScale.SOLAR_DAY | VOID_TimeScale.ROUNDED_SCALE);
   
  switch (flags)
{ {
return 21600d; // Earth day, sidereal
  case 0:
  return 86164.1d;
  // Earth day, solar (also rounded)
  case VOID_TimeScale.ROUNDED_SCALE | VOID_TimeScale.SOLAR_DAY:
  case VOID_TimeScale.ROUNDED_SCALE:
  case VOID_TimeScale.SOLAR_DAY:
  return 86400d;
  // Kerbin day, solar
  case VOID_TimeScale.KERBIN_TIME | VOID_TimeScale.SOLAR_DAY:
  return 21650.813d;
  // Kerbin day, sidereal (also rounded)
  default:
  return 21600d;
} }
else }
  }
   
  public static double SecondsPerYear
  {
  get
  {
  VOID_TimeScale flags = VOID_Data.Core.TimeScale &
  (VOID_TimeScale.KERBIN_TIME | VOID_TimeScale.SOLAR_DAY | VOID_TimeScale.ROUNDED_SCALE);
   
  switch (flags)
{ {
return 86164.1d; // Earth year, rounded
} case VOID_TimeScale.SOLAR_DAY | VOID_TimeScale.ROUNDED_SCALE:
} case VOID_TimeScale.ROUNDED_SCALE:
} return 60 * 60 * 24 * 365;
  // Kerbin year, rounded
public static double SecondsPerYear case VOID_TimeScale.KERBIN_TIME | VOID_TimeScale.SOLAR_DAY | VOID_TimeScale.ROUNDED_SCALE:
{ case VOID_TimeScale.KERBIN_TIME | VOID_TimeScale.ROUNDED_SCALE:
get return 60 * 60 * 6 * 426;
{ // Earth year, solar time
if (GameSettings.KERBIN_TIME) case VOID_TimeScale.SOLAR_DAY:
{ return 31556925.2507328;
return 9203545d; // Earth year, sidereal time
} case 0:
else return 31558149.7635456d;
{ // Kerbin year, solar & sidereal time
return 31558149d; default:
  return 9203544.61750141d;
} }
} }
} }
   
public static UnpackedTime FromSeconds(double seconds) public static UnpackedTime FromSeconds(double seconds)
{ {
UnpackedTime time = new UnpackedTime(); UnpackedTime time = new UnpackedTime();
   
time.years = (int)(seconds / SecondsPerYear); time.years = (int)(seconds / SecondsPerYear);
   
seconds %= SecondsPerYear; seconds %= SecondsPerYear;
   
time.days = (int)(seconds / SecondsPerDay); time.days = (int)(seconds / SecondsPerDay);
   
seconds %= SecondsPerDay; seconds %= SecondsPerDay;
   
time.hours = (int)(seconds / SecondsPerHour); time.hours = (int)(seconds / SecondsPerHour);
   
seconds %= SecondsPerHour; seconds %= SecondsPerHour;
   
time.minutes = (int)(seconds / SecondsPerMinute); time.minutes = (int)(seconds / SecondsPerMinute);
   
seconds %= SecondsPerMinute; seconds %= SecondsPerMinute;
   
time.seconds = seconds; time.seconds = seconds;
   
return time; return time;
} }
   
public static explicit operator UnpackedTime(double seconds) public static explicit operator UnpackedTime(double seconds)
{ {
return FromSeconds(seconds); return FromSeconds(seconds);
} }
   
public static implicit operator double(UnpackedTime time) public static implicit operator double(UnpackedTime time)
{ {
return time.ToSeconds(); return time.ToSeconds();
} }
   
public static UnpackedTime operator+ (UnpackedTime lhs, UnpackedTime rhs) public static UnpackedTime operator+ (UnpackedTime lhs, UnpackedTime rhs)
{ {
return FromSeconds(lhs.ToSeconds() + rhs.ToSeconds()); return FromSeconds(lhs.ToSeconds() + rhs.ToSeconds());
} }
   
public static UnpackedTime operator- (UnpackedTime lhs, UnpackedTime rhs) public static UnpackedTime operator- (UnpackedTime lhs, UnpackedTime rhs)
{ {
return FromSeconds(lhs.ToSeconds() - rhs.ToSeconds()); return FromSeconds(lhs.ToSeconds() - rhs.ToSeconds());
} }
   
public int years; public int years;
public int days; public int days;
public int hours; public int hours;
public int minutes; public int minutes;
public double seconds; public double seconds;
   
public double ToSeconds() public double ToSeconds()
{ {
return (double)years * SecondsPerYear + return (double)years * SecondsPerYear +
(double)days * SecondsPerDay + (double)days * SecondsPerDay +
(double)hours * SecondsPerHour + (double)hours * SecondsPerHour +
(double)minutes * SecondsPerMinute + (double)minutes * SecondsPerMinute +
seconds; seconds;
} }
   
public string FormatAsSpan() public string FormatAsSpan()
{ {
string format_1 = "{0:D1}y {1:D1}d {2:D2}h {3:D2}m {4:00.0}s"; string format_1 = "{0:D1}y {1:D1}d {2:D2}h {3:D2}m {4:00.0}s";
string format_2 = "{0:D1}d {1:D2}h {2:D2}m {3:00.0}s"; string format_2 = "{0:D1}d {1:D2}h {2:D2}m {3:00.0}s";
string format_3 = "{0:D2}h {1:D2}m {2:00.0}s"; string format_3 = "{0:D2}h {1:D2}m {2:00.0}s";
string format_4 = "{0:D2}m {1:00.0}s"; string format_4 = "{0:D2}m {1:00.0}s";
string format_5 = "{0:00.0}s"; string format_5 = "{0:00.0}s";
   
if (this.years > 0) if (this.years > 0)
{ {
return string.Format(format_1, this.years, this.days, this.hours, this.minutes, this.seconds); return string.Format(format_1, this.years, this.days, this.hours, this.minutes, this.seconds);
} }
else if (this.days > 0) else if (this.days > 0)
{ {
return string.Format(format_2, this.days, this.hours, this.minutes, this.seconds); return string.Format(format_2, this.days, this.hours, this.minutes, this.seconds);
} }
else if (this.hours > 0) else if (this.hours > 0)
{ {
return string.Format(format_3, this.hours, this.minutes, this.seconds); return string.Format(format_3, this.hours, this.minutes, this.seconds);
} }
else if (this.minutes > 0) else if (this.minutes > 0)
{ {
return string.Format(format_4, this.minutes, this.seconds); return string.Format(format_4, this.minutes, this.seconds);
} }
else else
{ {
return string.Format(format_5, this.seconds); return string.Format(format_5, this.seconds);
} }
} }
   
public string FormatAsDate() public string FormatAsDate()
{ {
string format = "Y{0:#0}, D{1:#0} {2:00}:{3:00}:{4:00.0}s"; string format = "Y{0:#0}, D{1:#0} {2:00}:{3:00}:{4:00.0}s";
   
return string.Format(format, years + 1, days + 1, hours, minutes, seconds); return string.Format(format, years + 1, days + 1, hours, minutes, seconds);
} }
   
public UnpackedTime(int years, int days, int hours, int minutes, double seconds) public UnpackedTime(int years, int days, int hours, int minutes, double seconds)
{ {
this.years = years; this.years = years;
this.days = days; this.days = days;
this.hours = hours; this.hours = hours;
this.minutes = minutes; this.minutes = minutes;
this.seconds = seconds; this.seconds = seconds;
} }
   
public UnpackedTime() : this(0, 0, 0, 0, 0d) {} public UnpackedTime() : this(0, 0, 0, 0, 0d) {}
} }
  #endregion
   
public static string UppercaseFirst(string s) public static string UppercaseFirst(string s)
{ {
if (string.IsNullOrEmpty(s)) if (string.IsNullOrEmpty(s))
{ {
return string.Empty; return string.Empty;
} }
char[] a = s.ToCharArray(); char[] a = s.ToCharArray();
a[0] = char.ToUpper(a[0]); a[0] = char.ToUpper(a[0]);
return new string(a); return new string(a);
} }
   
//transfer angles //transfer angles
public static double Nivvy_CalcTransferPhaseAngle(double r_current, double r_target, double grav_param) public static double Nivvy_CalcTransferPhaseAngle(double r_current, double r_target, double grav_param)
{ {
r_target /= 1000; r_target /= 1000;
r_current /= 1000; r_current /= 1000;
grav_param /= 1000000000; grav_param /= 1000000000;
   
double midpoint = (r_target + r_current) / 2; double midpoint = (r_target + r_current) / 2;
   
double T_target = (2 * Math.PI) * Math.Sqrt((r_target * r_target * r_target) / grav_param); double T_target = (2 * Math.PI) * Math.Sqrt((r_target * r_target * r_target) / grav_param);
double T_transfer = (2 * Math.PI) * Math.Sqrt((midpoint * midpoint * midpoint) / grav_param); double T_transfer = (2 * Math.PI) * Math.Sqrt((midpoint * midpoint * midpoint) / grav_param);
return 360 * (0.5 - (T_transfer / (2 * T_target))); return 360 * (0.5 - (T_transfer / (2 * T_target)));
} }
   
public static double Younata_DeltaVToGetToOtherBody(double mu, double r1, double r2) public static double Younata_DeltaVToGetToOtherBody(double mu, double r1, double r2)
{ {
/* /*
def deltaVToGetToOtherBody(mu, r1, r2): def deltaVToGetToOtherBody(mu, r1, r2):
# mu = gravity param of common orbiting body of r1 and r2 # mu = gravity param of common orbiting body of r1 and r2
# (e.g. for mun to minmus, mu is kerbin's gravity param # (e.g. for mun to minmus, mu is kerbin's gravity param
# r1 = initial body's orbit radius # r1 = initial body's orbit radius
# r2 = target body's orbit radius # r2 = target body's orbit radius
# return value is km/s # return value is km/s
sur1 = math.sqrt(mu / r1) sur1 = math.sqrt(mu / r1)
sr1r2 = math.sqrt(float(2*r2)/float(r1+r2)) sr1r2 = math.sqrt(float(2*r2)/float(r1+r2))
mult = sr1r2 - 1 mult = sr1r2 - 1
return sur1 * mult return sur1 * mult
*/ */
double sur1, sr1r2, mult; double sur1, sr1r2, mult;
sur1 = Math.Sqrt(mu / r1); sur1 = Math.Sqrt(mu / r1);
sr1r2 = Math.Sqrt((2 * r2) / (r1 + r2)); sr1r2 = Math.Sqrt((2 * r2) / (r1 + r2));
mult = sr1r2 - 1; mult = sr1r2 - 1;
return sur1 * mult; return sur1 * mult;
} }
   
public static double Younata_DeltaVToExitSOI(double mu, double r1, double r2, double v) public static double Younata_DeltaVToExitSOI(double mu, double r1, double r2, double v)
{ {
/* /*
def deltaVToExitSOI(mu, r1, r2, v): def deltaVToExitSOI(mu, r1, r2, v):
# mu = gravity param of current body # mu = gravity param of current body
# r1 = current orbit radius # r1 = current orbit radius
# r2 = SOI radius # r2 = SOI radius
# v = SOI exit velocity # v = SOI exit velocity
foo = r2 * (v**2) - 2 * mu foo = r2 * (v**2) - 2 * mu
bar = r1 * foo + (2 * r2 * mu) bar = r1 * foo + (2 * r2 * mu)
r = r1*r2 r = r1*r2
return math.sqrt(bar / r) return math.sqrt(bar / r)
*/ */
double foo = r2 * (v * v) - 2 * mu; double foo = r2 * (v * v) - 2 * mu;
double bar = r1 * foo + (2 * r2 * mu); double bar = r1 * foo + (2 * r2 * mu);
double r = r1 * r2; double r = r1 * r2;
return Math.Sqrt(bar / r); return Math.Sqrt(bar / r);
} }
   
public static double Younata_TransferBurnPoint(double r, double v, double angle, double mu) public static double Younata_TransferBurnPoint(double r, double v, double angle, double mu)
{ {
/* /*
def transferBurnPoint(r, v, angle, mu): def transferBurnPoint(r, v, angle, mu):
# r = parking orbit radius # r = parking orbit radius
# v = ejection velocity # v = ejection velocity
# angle = phase angle (from function phaseAngle()) # angle = phase angle (from function phaseAngle())
# mu = gravity param of current body. # mu = gravity param of current body.
epsilon = ((v**2)/2) - (mu / r) epsilon = ((v**2)/2) - (mu / r)
h = r * v * math.sin(angle) h = r * v * math.sin(angle)
e = math.sqrt(1 + ((2 * epsilon * h**2)/(mu**2))) e = math.sqrt(1 + ((2 * epsilon * h**2)/(mu**2)))
theta = math.acos(1.0 / e) theta = math.acos(1.0 / e)
degrees = theta * (180.0 / math.pi) degrees = theta * (180.0 / math.pi)
return 180 - degrees return 180 - degrees
*/ */
double epsilon, h, ee, theta, degrees; double epsilon, h, ee, theta, degrees;
epsilon = ((v * v) / 2) - (mu / r); epsilon = ((v * v) / 2) - (mu / r);
h = r * v * Math.Sin(angle); h = r * v * Math.Sin(angle);
ee = Math.Sqrt(1 + ((2 * epsilon * (h * h)) / (mu * mu))); ee = Math.Sqrt(1 + ((2 * epsilon * (h * h)) / (mu * mu)));
theta = Math.Acos(1.0 / ee); theta = Math.Acos(1.0 / ee);
degrees = theta * (180.0 / Math.PI); degrees = theta * (180.0 / Math.PI);
return 180 - degrees; return 180 - degrees;
// returns the ejection angle // returns the ejection angle
} }
   
public static double Adammada_CurrrentPhaseAngle( public static double Adammada_CurrrentPhaseAngle(
double body_LAN, double body_LAN,
double body_orbitPct, double body_orbitPct,
double origin_LAN, double origin_LAN,
double origin_orbitPct double origin_orbitPct
) )
{ {
double angle = (body_LAN / 360 + body_orbitPct) - (origin_LAN / 360 + origin_orbitPct); double angle = (body_LAN / 360 + body_orbitPct) - (origin_LAN / 360 + origin_orbitPct);
if (angle > 1) if (angle > 1)
angle = angle - 1; angle = angle - 1;
if (angle < 0) if (angle < 0)
angle = angle + 1; angle = angle + 1;
if (angle > 0.5) if (angle > 0.5)
angle = angle - 1; angle = angle - 1;
angle = angle * 360; angle = angle * 360;
return angle; return angle;
} }
   
public static double Adammada_CurrentEjectionAngle( public static double Adammada_CurrentEjectionAngle(
double vessel_long, double vessel_long,
double origin_rotAngle, double origin_rotAngle,
double origin_LAN, double origin_LAN,
double origin_orbitPct double origin_orbitPct
) )
{ {
//double eangle = ((FlightGlobals.ActiveVOID.vessel.longitude + orbiting.rotationAngle) - (orbiting.orbit.LAN / 360 + orbiting.orbit.orbitPercent) * 360); //double eangle = ((FlightGlobals.ActiveVOID.vessel.longitude + orbiting.rotationAngle) - (orbiting.orbit.LAN / 360 + orbiting.orbit.orbitPercent) * 360);
double eangle = ((vessel_long + origin_rotAngle) - (origin_LAN / 360 + origin_orbitPct) * 360); double eangle = ((vessel_long + origin_rotAngle) - (origin_LAN / 360 + origin_orbitPct) * 360);
   
while (eangle < 0) while (eangle < 0)
eangle = eangle + 360; eangle = eangle + 360;
while (eangle > 360) while (eangle > 360)
eangle = eangle - 360; eangle = eangle - 360;
if (eangle < 270) if (eangle < 270)
eangle = 90 - eangle; eangle = 90 - eangle;
else else
eangle = 450 - eangle; eangle = 450 - eangle;
return eangle; return eangle;
} }
   
public static double mrenigma03_calcphase(Vessel vessel, CelestialBody target) //calculates phase angle between the current body and target body public static double mrenigma03_calcphase(Vessel vessel, CelestialBody target) //calculates phase angle between the current body and target body
{ {
Vector3d vecthis = new Vector3d(); Vector3d vecthis = new Vector3d();
Vector3d vectarget = new Vector3d(); Vector3d vectarget = new Vector3d();
vectarget = target.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime()); vectarget = target.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime());
   
if ((vessel.mainBody.name == "Sun") || (vessel.mainBody.referenceBody.referenceBody.name == "Sun")) if ((vessel.mainBody.name == "Sun") || (vessel.mainBody.referenceBody.referenceBody.name == "Sun"))
{ {
vecthis = vessel.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime()); vecthis = vessel.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime());
} }
else else
{ {
vecthis = vessel.mainBody.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime()); vecthis = vessel.mainBody.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime());
} }
   
vecthis = Vector3d.Project(new Vector3d(vecthis.x, 0, vecthis.z), vecthis); vecthis = Vector3d.Project(new Vector3d(vecthis.x, 0, vecthis.z), vecthis);
vectarget = Vector3d.Project(new Vector3d(vectarget.x, 0, vectarget.z), vectarget); vectarget = Vector3d.Project(new Vector3d(vectarget.x, 0, vectarget.z), vectarget);
   
Vector3d prograde = new Vector3d(); Vector3d prograde = new Vector3d();
prograde = Quaternion.AngleAxis(90, Vector3d.forward) * vecthis; prograde = Quaternion.AngleAxis(90, Vector3d.forward) * vecthis;
   
double phase = Vector3d.Angle(vecthis, vectarget); double phase = Vector3d.Angle(vecthis, vectarget);
   
if (Vector3d.Angle(prograde, vectarget) > 90) if (Vector3d.Angle(prograde, vectarget) > 90)
phase = 360 - phase; phase = 360 - phase;
   
return (phase + 360) % 360; return (phase + 360) % 360;
} }
   
public static double adjustCurrPhaseAngle(double transfer_angle, double curr_phase) public static double adjustCurrPhaseAngle(double transfer_angle, double curr_phase)
{ {
if (transfer_angle < 0) if (transfer_angle < 0)
{ {
if (curr_phase > 0) if (curr_phase > 0)
return (-1 * (360 - curr_phase)); return (-1 * (360 - curr_phase));
else if (curr_phase < 0) else if (curr_phase < 0)
return curr_phase; return curr_phase;
} }
else if (transfer_angle > 0) else if (transfer_angle > 0)
{ {
if (curr_phase > 0) if (curr_phase > 0)
return curr_phase; return curr_phase;
else if (curr_phase < 0) else if (curr_phase < 0)
return (360 + curr_phase); return (360 + curr_phase);
} }
return curr_phase; return curr_phase;
} }
   
public static double adjust_current_ejection_angle(double curr_ejection) public static double adjust_current_ejection_angle(double curr_ejection)
{ {
//curr_ejection WILL need to be adjusted once for all transfers as it returns values ranging -180 to 180 //curr_ejection WILL need to be adjusted once for all transfers as it returns values ranging -180 to 180
// need 0-360 instead // need 0-360 instead
// //
// ie i have -17 in the screenshot // ie i have -17 in the screenshot
// need it to show 343 // need it to show 343
// //
// do this // do this
// //
// if < 0, add curr to 360 // 360 + (-17) = 343 // if < 0, add curr to 360 // 360 + (-17) = 343
// else its good as it is // else its good as it is
   
if (curr_ejection < 0) if (curr_ejection < 0)
return 360 + curr_ejection; return 360 + curr_ejection;
else else
return curr_ejection; return curr_ejection;
   
} }
   
public static double adjust_transfer_ejection_angle(double trans_ejection, double trans_phase) public static double adjust_transfer_ejection_angle(double trans_ejection, double trans_phase)
{ {
// if transfer_phase_angle < 0 its a lower transfer // if transfer_phase_angle < 0 its a lower transfer
//180 + curr_ejection //180 + curr_ejection
// else if transfer_phase_angle > 0 its good as it is // else if transfer_phase_angle > 0 its good as it is
   
if (trans_phase < 0) if (trans_phase < 0)
return 180 + trans_ejection; return 180 + trans_ejection;
else else
return trans_ejection; return trans_ejection;
   
} }
   
public static void display_transfer_angles_SUN2PLANET(CelestialBody body, Vessel vessel) public static void display_transfer_angles_SUN2PLANET(CelestialBody body, Vessel vessel)
{ {
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Phase angle (curr/trans):"); GUILayout.Label("Phase angle (curr/trans):");
GUILayout.Label( GUILayout.Label(
VOID_Tools.mrenigma03_calcphase(vessel, body).ToString("F3") + "° / " + VOID_Tools.Nivvy_CalcTransferPhaseAngle( VOID_Tools.mrenigma03_calcphase(vessel, body).ToString("F3") + "° / " + VOID_Tools.Nivvy_CalcTransferPhaseAngle(
vessel.orbit.semiMajorAxis, vessel.orbit.semiMajorAxis,
body.orbit.semiMajorAxis, body.orbit.semiMajorAxis,
vessel.mainBody.gravParameter vessel.mainBody.gravParameter
).ToString("F3") + "°", ).ToString("F3") + "°",
GUILayout.ExpandWidth(false) GUILayout.ExpandWidth(false)
); );
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Transfer velocity:"); GUILayout.Label("Transfer velocity:");
GUILayout.Label( GUILayout.Label(
(VOID_Tools.Younata_DeltaVToGetToOtherBody( (VOID_Tools.Younata_DeltaVToGetToOtherBody(
(vessel.mainBody.gravParameter / 1000000000), (vessel.mainBody.gravParameter / 1000000000),
(vessel.orbit.semiMajorAxis / 1000), (vessel.orbit.semiMajorAxis / 1000),
(body.orbit.semiMajorAxis / 1000) (body.orbit.semiMajorAxis / 1000)
) * 1000).ToString("F2") + "m/s", ) * 1000).ToString("F2") + "m/s",
GUILayout.ExpandWidth(false) GUILayout.ExpandWidth(false)
); );
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
   
public static void display_transfer_angles_PLANET2PLANET(CelestialBody body, Vessel vessel) public static void display_transfer_angles_PLANET2PLANET(CelestialBody body, Vessel vessel)
{ {
double dv1 = VOID_Tools.Younata_DeltaVToGetToOtherBody( double dv1 = VOID_Tools.Younata_DeltaVToGetToOtherBody(
(vessel.mainBody.referenceBody.gravParameter / 1000000000), (vessel.mainBody.referenceBody.gravParameter / 1000000000),
(vessel.mainBody.orbit.semiMajorAxis / 1000), (vessel.mainBody.orbit.semiMajorAxis / 1000),
(body.orbit.semiMajorAxis / 1000) (body.orbit.semiMajorAxis / 1000)
); );
double dv2 = VOID_Tools.Younata_DeltaVToExitSOI( double dv2 = VOID_Tools.Younata_DeltaVToExitSOI(
(vessel.mainBody.gravParameter / 1000000000), (vessel.mainBody.gravParameter / 1000000000),
(vessel.orbit.semiMajorAxis / 1000), (vessel.orbit.semiMajorAxis / 1000),
(vessel.mainBody.sphereOfInfluence / 1000), (vessel.mainBody.sphereOfInfluence / 1000),
Math.Abs(dv1) Math.Abs(dv1)
); );
   
double trans_ejection_angle = VOID_Tools.Younata_TransferBurnPoint( double trans_ejection_angle = VOID_Tools.Younata_TransferBurnPoint(
(vessel.orbit.semiMajorAxis / 1000), (vessel.orbit.semiMajorAxis / 1000),
dv2, dv2,
(Math.PI / 2.0), (Math.PI / 2.0),
(vessel.mainBody.gravParameter / 1000000000) (vessel.mainBody.gravParameter / 1000000000)
); );
double curr_ejection_angle = VOID_Tools.Adammada_CurrentEjectionAngle( double curr_ejection_angle = VOID_Tools.Adammada_CurrentEjectionAngle(
FlightGlobals.ActiveVessel.longitude, FlightGlobals.ActiveVessel.longitude,
FlightGlobals.ActiveVessel.orbit.referenceBody.rotationAngle, FlightGlobals.ActiveVessel.orbit.referenceBody.rotationAngle,
FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.LAN, FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.LAN,
FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.orbitPercent FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.orbitPercent
); );
   
double trans_phase_angle = VOID_Tools.Nivvy_CalcTransferPhaseAngle( double trans_phase_angle = VOID_Tools.Nivvy_CalcTransferPhaseAngle(
vessel.mainBody.orbit.semiMajorAxis, vessel.mainBody.orbit.semiMajorAxis,
body.orbit.semiMajorAxis, body.orbit.semiMajorAxis,
vessel.mainBody.referenceBody.gravParameter vessel.mainBody.referenceBody.gravParameter
) % 360; ) % 360;
double curr_phase_angle = VOID_Tools.Adammada_CurrrentPhaseAngle( double curr_phase_angle = VOID_Tools.Adammada_CurrrentPhaseAngle(
body.orbit.LAN, body.orbit.LAN,
body.orbit.orbitPercent, body.orbit.orbitPercent,
FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.LAN, FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.LAN,
FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.orbitPercent FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.orbitPercent
); );
   
double adj_phase_angle = VOID_Tools.adjustCurrPhaseAngle(trans_phase_angle, curr_phase_angle); double adj_phase_angle = VOID_Tools.adjustCurrPhaseAngle(trans_phase_angle, curr_phase_angle);
double adj_trans_ejection_angle = VOID_Tools.adjust_transfer_ejection_angle(trans_ejection_angle, trans_phase_angle); double adj_trans_ejection_angle = VOID_Tools.adjust_transfer_ejection_angle(trans_ejection_angle, trans_phase_angle);
double adj_curr_ejection_angle = VOID_Tools.adjust_current_ejection_angle(curr_ejection_angle); double adj_curr_ejection_angle = VOID_Tools.adjust_current_ejection_angle(curr_ejection_angle);
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Phase angle (curr/trans):"); GUILayout.Label("Phase angle (curr/trans):");
GUILayout.Label( GUILayout.Label(
adj_phase_angle.ToString("F3") + "° / " + trans_phase_angle.ToString("F3") + "°", adj_phase_angle.ToString("F3") + "° / " + trans_phase_angle.ToString("F3") + "°",
GUILayout.ExpandWidth(false) GUILayout.ExpandWidth(false)
); );
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Ejection angle (curr/trans):"); GUILayout.Label("Ejection angle (curr/trans):");
GUILayout.Label( GUILayout.Label(
adj_curr_ejection_angle.ToString("F3") + "° / " + adj_trans_ejection_angle.ToString("F3") + "°", adj_curr_ejection_angle.ToString("F3") + "° / " + adj_trans_ejection_angle.ToString("F3") + "°",
GUILayout.ExpandWidth(false) GUILayout.ExpandWidth(false)
); );
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Transfer velocity:"); GUILayout.Label("Transfer velocity:");
GUILayout.Label((dv2 * 1000).ToString("F2") + "m/s", GUILayout.ExpandWidth(false)); GUILayout.Label((dv2 * 1000).ToString("F2") + "m/s", GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
   
public static void display_transfer_angles_PLANET2MOON(CelestialBody body, Vessel vessel) public static void display_transfer_angles_PLANET2MOON(CelestialBody body, Vessel vessel)
{ {
double dv1 = VOID_Tools.Younata_DeltaVToGetToOtherBody( double dv1 = VOID_Tools.Younata_DeltaVToGetToOtherBody(
(vessel.mainBody.gravParameter / 1000000000), (vessel.mainBody.gravParameter / 1000000000),
(vessel.orbit.semiMajorAxis / 1000), (vessel.orbit.semiMajorAxis / 1000),
(body.orbit.semiMajorAxis / 1000) (body.orbit.semiMajorAxis / 1000)
); );
   
double trans_phase_angle = VOID_Tools.Nivvy_CalcTransferPhaseAngle( double trans_phase_angle = VOID_Tools.Nivvy_CalcTransferPhaseAngle(
vessel.orbit.semiMajorAxis, vessel.orbit.semiMajorAxis,
body.orbit.semiMajorAxis, body.orbit.semiMajorAxis,
vessel.mainBody.gravParameter vessel.mainBody.gravParameter
); );
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Phase angle (curr/trans):"); GUILayout.Label("Phase angle (curr/trans):");
GUILayout.Label( GUILayout.Label(
VOID_Tools.mrenigma03_calcphase(vessel, body).ToString("F3") + "° / " + trans_phase_angle.ToString("F3") + "°", VOID_Tools.mrenigma03_calcphase(vessel, body).ToString("F3") + "° / " + trans_phase_angle.ToString("F3") + "°",
GUILayout.ExpandWidth(false) GUILayout.ExpandWidth(false)
); );
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Transfer velocity:"); GUILayout.Label("Transfer velocity:");
GUILayout.Label((dv1 * 1000).ToString("F2") + "m/s", GUILayout.ExpandWidth(false)); GUILayout.Label((dv1 * 1000).ToString("F2") + "m/s", GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
   
public static void display_transfer_angles_MOON2MOON(CelestialBody body, Vessel vessel) public static void display_transfer_angles_MOON2MOON(CelestialBody body, Vessel vessel)
{ {
double dv1 = VOID_Tools.Younata_DeltaVToGetToOtherBody( double dv1 = VOID_Tools.Younata_DeltaVToGetToOtherBody(
(vessel.mainBody.referenceBody.gravParameter / 1000000000), (vessel.mainBody.referenceBody.gravParameter / 1000000000),
(vessel.mainBody.orbit.semiMajorAxis / 1000), (vessel.mainBody.orbit.semiMajorAxis / 1000),
(body.orbit.semiMajorAxis / 1000) (body.orbit.semiMajorAxis / 1000)
); );
double dv2 = VOID_Tools.Younata_DeltaVToExitSOI( double dv2 = VOID_Tools.Younata_DeltaVToExitSOI(
(vessel.mainBody.gravParameter / 1000000000), (vessel.mainBody.gravParameter / 1000000000),
(vessel.orbit.semiMajorAxis / 1000), (vessel.orbit.semiMajorAxis / 1000),
(vessel.mainBody.sphereOfInfluence / 1000), (vessel.mainBody.sphereOfInfluence / 1000),
Math.Abs(dv1) Math.Abs(dv1)
); );
double trans_ejection_angle = VOID_Tools.Younata_TransferBurnPoint( double trans_ejection_angle = VOID_Tools.Younata_TransferBurnPoint(
(vessel.orbit.semiMajorAxis / 1000), (vessel.orbit.semiMajorAxis / 1000),
dv2, dv2,
(Math.PI / 2.0), (Math.PI / 2.0),
(vessel.mainBody.gravParameter / 1000000000) (vessel.mainBody.gravParameter / 1000000000)
); );
   
double curr_phase_angle = VOID_Tools.Adammada_CurrrentPhaseAngle( double curr_phase_angle = VOID_Tools.Adammada_CurrrentPhaseAngle(
body.orbit.LAN, body.orbit.LAN,
body.orbit.orbitPercent, body.orbit.orbitPercent,
FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.LAN, FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.LAN,
FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.orbitPercent FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.orbitPercent
); );
double curr_ejection_angle = VOID_Tools.Adammada_CurrentEjectionAngle( double curr_ejection_angle = VOID_Tools.Adammada_CurrentEjectionAngle(
FlightGlobals.ActiveVessel.longitude, FlightGlobals.ActiveVessel.longitude,
FlightGlobals.ActiveVessel.orbit.referenceBody.rotationAngle, FlightGlobals.ActiveVessel.orbit.referenceBody.rotationAngle,
FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.LAN, FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.LAN,
FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.orbitPercent FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.orbitPercent
); );
   
double trans_phase_angle = VOID_Tools.Nivvy_CalcTransferPhaseAngle( double trans_phase_angle = VOID_Tools.Nivvy_CalcTransferPhaseAngle(
vessel.mainBody.orbit.semiMajorAxis, vessel.mainBody.orbit.semiMajorAxis,
body.orbit.semiMajorAxis, body.orbit.semiMajorAxis,
vessel.mainBody.referenceBody.gravParameter vessel.mainBody.referenceBody.gravParameter
) % 360; ) % 360;
   
double adj_phase_angle = VOID_Tools.adjustCurrPhaseAngle(trans_phase_angle, curr_phase_angle); double adj_phase_angle = VOID_Tools.adjustCurrPhaseAngle(trans_phase_angle, curr_phase_angle);
//double adj_ejection_angle = adjustCurrEjectionAngle(trans_phase_angle, curr_ejection_angle); //double adj_ejection_angle = adjustCurrEjectionAngle(trans_phase_angle, curr_ejection_angle);
   
//new stuff //new stuff
// //
double adj_trans_ejection_angle = VOID_Tools.adjust_transfer_ejection_angle(trans_ejection_angle, trans_phase_angle); double adj_trans_ejection_angle = VOID_Tools.adjust_transfer_ejection_angle(trans_ejection_angle, trans_phase_angle);
double adj_curr_ejection_angle = VOID_Tools.adjust_current_ejection_angle(curr_ejection_angle); double adj_curr_ejection_angle = VOID_Tools.adjust_current_ejection_angle(curr_ejection_angle);
// //
// //
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Phase angle (curr/trans):"); GUILayout.Label("Phase angle (curr/trans):");
GUILayout.Label( GUILayout.Label(
adj_phase_angle.ToString("F3") + "° / " + trans_phase_angle.ToString("F3") + "°", adj_phase_angle.ToString("F3") + "° / " + trans_phase_angle.ToString("F3") + "°",
GUILayout.ExpandWidth(false) GUILayout.ExpandWidth(false)
); );
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Ejection angle (curr/trans):"); GUILayout.Label("Ejection angle (curr/trans):");
GUILayout.Label( GUILayout.Label(
adj_curr_ejection_angle.ToString("F3") + "° / " + adj_trans_ejection_angle.ToString("F3") + "°", adj_curr_ejection_angle.ToString("F3") + "° / " + adj_trans_ejection_angle.ToString("F3") + "°",
GUILayout.ExpandWidth(false) GUILayout.ExpandWidth(false)
); );
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Transfer velocity:"); GUILayout.Label("Transfer velocity:");
GUILayout.Label((dv2 * 1000).ToString("F2") + "m/s", GUILayout.ExpandWidth(false)); GUILayout.Label((dv2 * 1000).ToString("F2") + "m/s", GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
   
public static string get_heading_text(double heading) public static string get_heading_text(double heading)
{ {
if (heading > 348.75 || heading <= 11.25) if (heading > 348.75 || heading <= 11.25)
return "N"; return "N";
else if (heading > 11.25 && heading <= 33.75) else if (heading > 11.25 && heading <= 33.75)
return "NNE"; return "NNE";
else if (heading > 33.75 && heading <= 56.25) else if (heading > 33.75 && heading <= 56.25)
return "NE"; return "NE";
else if (heading > 56.25 && heading <= 78.75) else if (heading > 56.25 && heading <= 78.75)
return "ENE"; return "ENE";
else if (heading > 78.75 && heading <= 101.25) else if (heading > 78.75 && heading <= 101.25)
return "E"; return "E";
else if (heading > 101.25 && heading <= 123.75) else if (heading > 101.25 && heading <= 123.75)
return "ESE"; return "ESE";
else if (heading > 123.75 && heading <= 146.25) else if (heading > 123.75 && heading <= 146.25)
return "SE"; return "SE";
else if (heading > 146.25 && heading <= 168.75) else if (heading > 146.25 && heading <= 168.75)
return "SSE"; return "SSE";
else if (heading > 168.75 && heading <= 191.25) else if (heading > 168.75 && heading <= 191.25)
return "S"; return "S";
else if (heading > 191.25 && heading <= 213.75) else if (heading > 191.25 && heading <= 213.75)
return "SSW"; return "SSW";
else if (heading > 213.75 && heading <= 236.25) else if (heading > 213.75 && heading <= 236.25)
return "SW"; return "SW";
else if (heading > 236.25 && heading <= 258.75) else if (heading > 236.25 && heading <= 258.75)
return "WSW"; return "WSW";
else if (heading > 258.75 && heading <= 281.25) else if (heading > 258.75 && heading <= 281.25)
return "W"; return "W";
else if (heading > 281.25 && heading <= 303.75) else if (heading > 281.25 && heading <= 303.75)
return "WNW"; return "WNW";
else if (heading > 303.75 && heading <= 326.25) else if (heading > 303.75 && heading <= 326.25)
return "NW"; return "NW";
else if (heading > 326.25 && heading <= 348.75) else if (heading > 326.25 && heading <= 348.75)
return "NNW"; return "NNW";
else else
return ""; return "";
} }
} }
   
public class CBListComparer : IComparer<CelestialBody> public class CBListComparer : IComparer<CelestialBody>
{ {
public int Compare(CelestialBody bodyA, CelestialBody bodyB) public int Compare(CelestialBody bodyA, CelestialBody bodyB)
{ {
Tools.PostDebugMessage(this, "got bodyA: {0} & bodyB: {1}", bodyA, bodyB); Tools.PostDebugMessage(this, "got bodyA: {0} & bodyB: {1}", bodyA, bodyB);
   
if (bodyA == null && bodyB == null) if (bodyA == null && bodyB == null)
{ {
Tools.PostDebugMessage(this, "both bodies are null, returning 0"); Tools.PostDebugMessage(this, "both bodies are null, returning 0");
return 0; return 0;
} }
if (bodyA == null) if (bodyA == null)
{ {
Tools.PostDebugMessage(this, "bodyA is null, returning -1"); Tools.PostDebugMessage(this, "bodyA is null, returning -1");
return -1; return -1;
} }
if (bodyB == null) if (bodyB == null)
{ {
Tools.PostDebugMessage(this, "bodyB is null, returning 1"); Tools.PostDebugMessage(this, "bodyB is null, returning 1");
return 1; return 1;
} }
   
Tools.PostDebugMessage(this, "bodies are not null, carrying on"); Tools.PostDebugMessage(this, "bodies are not null, carrying on");
   
if (object.ReferenceEquals(bodyA, bodyB)) if (object.ReferenceEquals(bodyA, bodyB))
{ {
Tools.PostDebugMessage(this, "bodies are equal, returning 0"); Tools.PostDebugMessage(this, "bodies are equal, returning 0");
return 0; return 0;
} }
   
Tools.PostDebugMessage(this, "bodies are not equal, carrying on"); Tools.PostDebugMessage(this, "bodies are not equal, carrying on");
   
if (bodyA.orbitDriver == null) if (bodyA.orbitDriver == null)
{ {
Tools.PostDebugMessage(this, "bodyA.orbit is null (bodyA is the sun, returning 1"); Tools.PostDebugMessage(this, "bodyA.orbit is null (bodyA is the sun, returning 1");
return 1; return 1;
} }
if (bodyB.orbitDriver == null) if (bodyB.orbitDriver == null)
{ {
Tools.PostDebugMessage(this, "bodyB.orbit is null (bodyB is the sun, returning -1"); Tools.PostDebugMessage(this, "bodyB.orbit is null (bodyB is the sun, returning -1");
return -1; return -1;
} }
   
Tools.PostDebugMessage(this, "orbits are not null, carrying on"); Tools.PostDebugMessage(this, "orbits are not null, carrying on");
   
if (bodyA.orbit.referenceBody == bodyB.orbit.referenceBody) if (bodyA.orbit.referenceBody == bodyB.orbit.referenceBody)
{ {
Tools.PostDebugMessage(this, "bodies share a parent, comparing SMAs"); Tools.PostDebugMessage(this, "bodies share a parent, comparing SMAs");
return -bodyA.orbit.semiMajorAxis.CompareTo(bodyB.orbit.semiMajorAxis); return -bodyA.orbit.semiMajorAxis.CompareTo(bodyB.orbit.semiMajorAxis);
} }
   
Tools.PostDebugMessage(this, "orbits do not share a parent, carrying on"); Tools.PostDebugMessage(this, "orbits do not share a parent, carrying on");
   
if (bodyA.hasAncestor(bodyB)) if (bodyA.hasAncestor(bodyB))
{ {
Tools.PostDebugMessage(this, "bodyA is a moon or sub-moon of bodyB, returning -1"); Tools.PostDebugMessage(this, "bodyA is a moon or sub-moon of bodyB, returning -1");
return -1; return -1;
} }
if (bodyB.hasAncestor(bodyA)) if (bodyB.hasAncestor(bodyA))
{ {
Tools.PostDebugMessage(this, "bodyA is a moon or sub-moon of bodyB, returning 1"); Tools.PostDebugMessage(this, "bodyA is a moon or sub-moon of bodyB, returning 1");
return 1; return 1;
} }
   
Tools.PostDebugMessage(this, "bodies do not have an obvious relationship, searching for one"); Tools.PostDebugMessage(this, "bodies do not have an obvious relationship, searching for one");
   
if (VOID_Tools.NearestRelatedParents(ref bodyA, ref bodyB)) if (VOID_Tools.NearestRelatedParents(ref bodyA, ref bodyB))
{ {
Tools.PostDebugMessage(this, "good relation {0} and {1}, comparing", bodyA.bodyName, bodyB.bodyName); Tools.PostDebugMessage(this, "good relation {0} and {1}, comparing", bodyA.bodyName, bodyB.bodyName);
return this.Compare(bodyA, bodyB); return this.Compare(bodyA, bodyB);
} }
   
Tools.PostDebugMessage(this, "bad relation {0} and {1}, giving up", bodyA.bodyName, bodyB.bodyName); Tools.PostDebugMessage(this, "bad relation {0} and {1}, giving up", bodyA.bodyName, bodyB.bodyName);
   
return 0; return 0;
} }
} }
} }
   
<?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} ${ProjectDir}\GameData\VOID\Plugins\" /> <Command type="AfterBuild" command="xcopy /Y ${TargetFile} ${ProjectDir}\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} ${ProjectDir}\GameData\VOID\Plugins\" /> <Command type="AfterBuild" command="xcopy /Y ${TargetFile} ${ProjectDir}\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} ${ProjectDir}/GameData/${ProjectName}/Plugins/" /> <Command type="AfterBuild" command="cp -afv ${TargetFile} ${ProjectDir}/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} ${ProjectDir}/GameData/${ProjectName}/Plugins/" /> <Command type="AfterBuild" command="cp -afv ${TargetFile} ${ProjectDir}/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="VOID_HUD.cs" /> <Compile Include="VOID_HUD.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_EditorHUD.cs" /> <Compile Include="VOID_EditorHUD.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" /> <Compile Include="VOID_Data.cs" />
<Compile Include="VOIDMaster_Flight.cs" /> <Compile Include="VOIDMaster_Flight.cs" />
<Compile Include="VOIDMaster_Editor.cs" /> <Compile Include="VOIDMaster_Editor.cs" />
<Compile Include="VOIDMaster_SpaceCentre.cs" /> <Compile Include="VOIDMaster_SpaceCentre.cs" />
<Compile Include="VOIDCore_SpaceCentre.cs" /> <Compile Include="VOIDCore_SpaceCentre.cs" />
<Compile Include="VOIDCore_Flight.cs" /> <Compile Include="VOIDCore_Flight.cs" />
<Compile Include="VOIDCore_Editor.cs" /> <Compile Include="VOIDCore_Editor.cs" />
<Compile Include="VOIDCore_Generic.cs" /> <Compile Include="VOIDCore_Generic.cs" />
<Compile Include="API\IVOID_Module.cs" /> <Compile Include="API\IVOID_Module.cs" />
<Compile Include="API\VOIDCore.cs" /> <Compile Include="API\VOIDCore.cs" />
<Compile Include="API\IVOID_SaveValue.cs" /> <Compile Include="API\IVOID_SaveValue.cs" />
<Compile Include="API\IVOID_DataValue.cs" /> <Compile Include="API\IVOID_DataValue.cs" />
<Compile Include="API\VOID_Module.cs" /> <Compile Include="API\VOID_Module.cs" />
<Compile Include="Tools\VOID_Tools.cs" /> <Compile Include="Tools\VOID_Tools.cs" />
<Compile Include="Tools\VOID_DataValue.cs" /> <Compile Include="Tools\VOID_DataValue.cs" />
<Compile Include="Tools\VOID_SaveValue.cs" /> <Compile Include="Tools\VOID_SaveValue.cs" />
<Compile Include="API\VOID_HUDModule.cs" /> <Compile Include="API\VOID_HUDModule.cs" />
<Compile Include="API\VOID_SingletonModule.cs" />  
<Compile Include="API\Attributes\VOID_ScenesAttribute.cs" /> <Compile Include="API\Attributes\VOID_ScenesAttribute.cs" />
<Compile Include="API\Attributes\AVOID_SaveValue.cs" /> <Compile Include="API\Attributes\AVOID_SaveValue.cs" />
<Compile Include="API\VOIDMaster.cs" /> <Compile Include="API\VOIDMaster.cs" />
<Compile Include="API\Attributes\VOID_GameModesAttribute.cs" /> <Compile Include="API\Attributes\VOID_GameModesAttribute.cs" />
  <Compile Include="VOID_ConfigWindow.cs" />
  <Compile Include="Tools\VOID_Localization.cs" />
  <Compile Include="Tools\VOID_StageExtensions.cs" />
  <Compile Include="API\VOID_SingletonCore.cs" />
  <Compile Include="API\VOID_SingletonWindow.cs" />
  <Compile Include="API\Enums.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>
<ItemGroup> <ItemGroup>
<None Include="GameData\VOID\Textures\ATM_VOID.cfg" /> <None Include="GameData\VOID\Textures\ATM_VOID.cfg" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="API\" /> <Folder Include="API\" />
<Folder Include="Tools\" /> <Folder Include="Tools\" />
<Folder Include="API\Attributes\" /> <Folder Include="API\Attributes\" />
</ItemGroup> </ItemGroup>
</Project> </Project>
   
// VOID // VOID
// //
// VOID_EditorCore.cs // VOID_EditorCore.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 KerbalEngineer.VesselSimulator; using KerbalEngineer.VesselSimulator;
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
{ {
[VOID_Scenes(GameScenes.EDITOR)] [VOID_Scenes(GameScenes.EDITOR)]
public class VOIDCore_Editor : VOIDCore_Generic<VOIDCore_Editor> public class VOIDCore_Editor : VOIDCore_Generic<VOIDCore_Editor>
{ {
public VOIDCore_Editor() : base()  
{  
this.Name = "VOID Core: Editor";  
}  
   
public override void FixedUpdate() {} public override void FixedUpdate() {}
} }
} }
   
   
// VOID // VOID
// //
// VOIDCore_Flight.cs // VOIDCore_Flight.cs
// //
// Copyright © 2015, toadicus // Copyright © 2015, 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 UnityEngine; using UnityEngine;
using ToadicusTools; using ToadicusTools;
   
namespace VOID namespace VOID
{ {
[VOID_Scenes(GameScenes.FLIGHT)] [VOID_Scenes(GameScenes.FLIGHT)]
public class VOIDCore_Flight : VOIDCore_Generic<VOIDCore_Flight> public class VOIDCore_Flight : VOIDCore_Generic<VOIDCore_Flight>
{ {
public VOIDCore_Flight()  
{  
base.Name = "VOID Core: Flight";  
}  
   
public override void DrawConfigurables() public override void DrawConfigurables()
{ {
if (HighLogic.LoadedSceneIsFlight) if (HighLogic.LoadedSceneIsFlight)
{ {
this.consumeResource.value = GUITools.Toggle(this.consumeResource, "Consume Resources"); this.consumeResource.value = GUITools.Toggle(this.consumeResource, "Consume Resources");
} }
   
base.DrawConfigurables(); base.DrawConfigurables();
} }
} }
} }
   
   
// VOID // VOID
// //
// VOIDCore_Generic.cs // VOIDCore_Generic.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 KerbalEngineer.VesselSimulator; using KerbalEngineer.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 abstract class VOIDCore_Generic<T> : VOID_SingletonModule<T>, IVOID_Module, IDisposable public abstract class VOIDCore_Generic<T> : VOID_SingletonCore<T>, IVOID_Module, IDisposable
where T : VOID_Module, new() where T : VOID_Module, new()
{ {
/* /*
* Fields * Fields
* */ * */
protected string VoidName = "VOID"; protected string VoidName = "VOID";
protected string VoidVersion; protected string VoidVersion;
   
[AVOID_SaveValue("configValue")] [AVOID_SaveValue("configValue")]
protected VOID_SaveValue<int> _configVersion = VOIDCore.CONFIG_VERSION; protected VOID_SaveValue<int> configVersion = (VOID_SaveValue<int>)VOIDCore.CONFIG_VERSION;
   
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")]  
protected VOID_SaveValue<Rect> mainWindowPos = new Rect(475, 575, 10f, 10f);  
[AVOID_SaveValue("mainGuiMinimized")]  
protected VOID_SaveValue<bool> mainGuiMinimized = false;  
   
[AVOID_SaveValue("configWindowPos")]  
protected VOID_SaveValue<Rect> configWindowPos = new Rect(825, 625, 10f, 10f);  
[AVOID_SaveValue("configWindowMinimized")]  
   
protected VOID_SaveValue<bool> configWindowMinimized = true;  
   
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;
   
  private bool _useToolbarManager;
   
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 CelestialBody _homeBody; protected CelestialBody homeBody;
   
[AVOID_SaveValue("togglePower")] [AVOID_SaveValue("togglePower")]
public VOID_SaveValue<bool> togglePower = true; public VOID_SaveValue<bool> togglePower = (VOID_SaveValue<bool>)true;
   
public override bool powerAvailable { get; protected set; } public override bool powerAvailable { get; protected set; }
   
[AVOID_SaveValue("consumeResource")] [AVOID_SaveValue("consumeResource")]
protected VOID_SaveValue<bool> consumeResource = false; protected VOID_SaveValue<bool> consumeResource = (VOID_SaveValue<bool>)false;
   
[AVOID_SaveValue("resourceName")] [AVOID_SaveValue("resourceName")]
protected VOID_SaveValue<string> resourceName = "ElectricCharge"; protected VOID_SaveValue<string> resourceName = (VOID_SaveValue<string>)"ElectricCharge";
   
[AVOID_SaveValue("resourceRate")] [AVOID_SaveValue("resourceRate")]
protected VOID_SaveValue<float> resourceRate = 0.2f; protected VOID_SaveValue<float> resourceRate = (VOID_SaveValue<float>)0.2f;
   
[AVOID_SaveValue("updatePeriod")] [AVOID_SaveValue("updatePeriod")]
protected VOID_SaveValue<double> _updatePeriod = 1001f / 15000f; protected VOID_SaveValue<double> updatePeriod = (VOID_SaveValue<double>)(1001f / 15000f);
protected string stringFrequency; protected string stringFrequency;
   
[AVOID_SaveValue("vesselSimActive")] [AVOID_SaveValue("vesselSimActive")]
protected VOID_SaveValue<bool> vesselSimActive; protected VOID_SaveValue<bool> vesselSimActive;
   
  [AVOID_SaveValue("timeScaleFlags")]
  protected VOID_SaveValue<UInt32> timeScaleFlags;
   
// Vessel Type Housekeeping // Vessel Type Housekeeping
protected List<VesselType> _allVesselTypes = new List<VesselType>();  
protected bool vesselTypesLoaded = false; protected bool vesselTypesLoaded = false;
   
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 1", "KSP window 1",
  "KSP window 3",
"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 override bool configDirty { get; set; } public override bool configDirty { get; set; }
   
internal IButton ToolbarButton; protected IButton ToolbarButton;
  protected ApplicationLauncherButton AppLauncherButton;
internal ApplicationLauncherButton AppLauncherButton; protected IconState iconState;
   
/* /*
* Properties * Properties
* */ * */
public override int configVersion public override bool Active
{ {
get get
{ {
return this._configVersion; return base.Active;
} }
} set
  {
public bool factoryReset if (value != base.Active)
  {
  this.SetIconTexture(this.powerState | this.activeState);
  }
   
  base.Active = value;
  }
  }
  public override IList<CelestialBody> AllBodies
  {
  get
  {
  return FlightGlobals.Bodies.AsReadOnly();
  }
  }
   
  public override VesselType[] AllVesselTypes
{ {
get; get;
protected set; protected set;
} }
   
public override List<IVOID_Module> Modules public override int ConfigVersion
{ {
get get
{ {
return this._modules; return this.configVersion;
  }
  }
   
  public bool FactoryReset
  {
  get;
  protected set;
  }
   
  public override CelestialBody HomeBody
  {
  get
  {
  if (this.homeBody == null)
  {
  if (Planetarium.fetch != null)
  {
  this.homeBody = Planetarium.fetch.Home;
  }
  }
   
  return this.homeBody;
  }
  }
   
  public override IList<IVOID_Module> Modules
  {
  get
  {
  return this.modules.AsReadOnly();
} }
} }
   
public override GUISkin Skin public override 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 override int windowID public override List<CelestialBody> SortedBodyList
{  
get  
{  
if (this._windowID == 0)  
{  
this._windowID = this.windowBaseID;  
}  
return this._windowID++;  
}  
}  
   
public override List<CelestialBody> allBodies  
{  
get  
{  
return FlightGlobals.Bodies;  
}  
}  
   
public override List<CelestialBody> sortedBodyList  
{ {
get; get;
protected set; protected set;
} }
   
public override CelestialBody HomeBody public override double UpdatePeriod
{ {
get get
{ {
if (this._homeBody == null) return this.updatePeriod;
{ }
if (Planetarium.fetch != null) }
{  
this._homeBody = Planetarium.fetch.Home; public override float UpdateTimer
}  
}  
   
return this._homeBody;  
}  
}  
   
public override List<VesselType> allVesselTypes  
{  
get  
{  
return this._allVesselTypes;  
}  
}  
   
public override float updateTimer  
{ {
get; get;
protected set; protected set;
} }
   
  public override int WindowID
public override double updatePeriod {
{ get
get {
{ if (this.windowID == 0)
return this._updatePeriod; {
  this.windowID = this.windowBaseID;
  }
  return this.windowID++;
} }
} }
   
public override Stage[] Stages public override Stage[] Stages
{ {
get; get;
protected set; protected set;
} }
   
public override Stage LastStage public override Stage LastStage
{ {
get; get;
protected set; protected set;
} }
   
  public override VOID_TimeScale TimeScale
  {
  get
  {
  return (VOID_TimeScale)this.timeScaleFlags.value;
  }
  protected set
  {
  this.timeScaleFlags.value = (UInt32)value;
  }
  }
   
  protected IconState activeState
  {
  get
  {
  if (this.Active)
  {
  return IconState.Inactive;
  }
  else
  {
  return IconState.Active;
  }
   
  }
  }
   
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 virtual ApplicationLauncher.AppScenes appIconVisibleScenes
{ {
get get
{ {
if (this.mainGuiMinimized) return HighLogic.LoadedScene.ToAppScenes();
{ }
return IconState.Inactive; }
}  
else protected bool useToolbarManager
{ {
return IconState.Active; get
} {
  return _useToolbarManager & ToolbarManager.ToolbarAvailable;
}  
}  
   
protected bool UseToolbarManager  
{  
get  
{  
return useToolbarManager & ToolbarManager.ToolbarAvailable;  
} }
set set
{ {
if (useToolbarManager == value) if (_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; _useToolbarManager = value;
}  
}  
   
protected virtual ApplicationLauncher.AppScenes appIconVisibleScenes  
{  
get  
{  
return HighLogic.LoadedScene.ToAppScenes();  
} }
} }
   
/* /*
* Events * Events
* */ * */
public override event VOIDEventHandler onApplicationQuit; public override event VOIDEventHandler onApplicationQuit;
public override event VOIDEventHandler onSkinChanged; public override event VOIDEventHandler onSkinChanged;
   
/* /*
* 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) this.SetIconTexture();
{  
  if (this.Active)
Rect _mainWindowPos = this.mainWindowPos; {
  base.DrawGUI();
_mainWindowPos = GUILayout.Window(  
this.windowID,  
_mainWindowPos,  
VOID_Tools.GetWindowHandler(  
VOID_WindowModule.DecorateWindow(  
this.VOIDMainWindow,  
_mainWindowPos,  
(bool active) => { this.mainGuiMinimized = !active; }  
)),  
string.Join(" ", new string[] { this.VoidName, this.VoidVersion }),  
GUILayout.Width(250f),  
GUILayout.Height(50f),  
GUILayout.ExpandWidth(true),  
GUILayout.ExpandHeight(true)  
);  
   
if (HighLogic.LoadedSceneIsEditor)  
{  
_mainWindowPos = Tools.ClampRectToEditorPad(_mainWindowPos);  
}  
else  
{  
_mainWindowPos = Tools.ClampRectToScreen(_mainWindowPos);  
}  
   
if (_mainWindowPos != this.mainWindowPos)  
{  
this.mainWindowPos = _mainWindowPos;  
}  
}  
   
if (!this.configWindowMinimized && !this.mainGuiMinimized)  
{  
Rect _configWindowPos = this.configWindowPos;  
   
_configWindowPos = GUILayout.Window(  
this.windowID,  
_configWindowPos,  
VOID_Tools.GetWindowHandler(VOID_WindowModule.DecorateWindow(  
this.VOIDConfigWindow,  
_configWindowPos,  
(bool active) => { this.configWindowMinimized = !active; }  
)),  
string.Join(" ", new string[] { this.VoidName, "Configuration" }),  
GUILayout.Width(250),  
GUILayout.Height(50)  
);  
   
if (HighLogic.LoadedSceneIsEditor)  
{  
_configWindowPos = Tools.ClampRectToEditorPad(_configWindowPos);  
}  
else  
{  
_configWindowPos = Tools.ClampRectToScreen(_configWindowPos);  
}  
   
if (_configWindowPos != this.configWindowPos)  
{  
this.configWindowPos = _configWindowPos;  
}  
} }
} }
   
public virtual void Update() public virtual void Update()
{ {
this.LoadBeforeUpdate(); this.LoadBeforeUpdate();
   
if ( if (
this.vesselSimActive && this.vesselSimActive &&
( (
this.vessel != null || this.Vessel != null ||
( (
HighLogic.LoadedSceneIsEditor && HighLogic.LoadedSceneIsEditor &&
EditorLogic.RootPart != null && EditorLogic.RootPart != null &&
EditorLogic.SortedShipList.Count > 0 EditorLogic.SortedShipList.Count > 0
) )
) )
) )
{ {
Tools.PostDebugMessage(this, "Updating SimManager."); Tools.PostDebugMessage(this, "Updating SimManager.");
this.UpdateSimManager(); this.UpdateSimManager();
} }
   
if (!this.guiRunning) if (!this.GUIRunning)
{ {
this.StartGUI(); this.StartGUI();
} }
   
foreach (IVOID_Module module in this.Modules) foreach (IVOID_Module module in this.modules)
{ {
if ( if (
!module.guiRunning && !module.GUIRunning &&
module.toggleActive && module.Active &&
module.inValidScene && module.InValidScene &&
( (
!HighLogic.LoadedSceneIsEditor || !HighLogic.LoadedSceneIsEditor ||
(EditorLogic.RootPart != null && EditorLogic.SortedShipList.Count > 0) (EditorLogic.RootPart != null && EditorLogic.SortedShipList.Count > 0)
) )
) )
{ {
module.StartGUI(); module.StartGUI();
} }
if ( if (
module.guiRunning && module.GUIRunning &&
( (
!module.toggleActive || !module.Active ||
!this.togglePower || !this.togglePower ||
!module.inValidScene || !module.InValidScene ||
this.factoryReset || this.FactoryReset ||
( (
HighLogic.LoadedSceneIsEditor && HighLogic.LoadedSceneIsEditor &&
(EditorLogic.RootPart == null || EditorLogic.SortedShipList.Count == 0) (EditorLogic.RootPart == null || EditorLogic.SortedShipList.Count == 0)
) )
) )
) )
{ {
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); }
} }
}  
  foreach (IVOID_Module module in this.modules)
foreach (IVOID_Module module in this.Modules)  
{ {
if (module is IVOID_BehaviorModule) if (module is IVOID_BehaviorModule)
{ {
((IVOID_BehaviorModule)module).FixedUpdate(); ((IVOID_BehaviorModule)module).FixedUpdate();
} }
} }
} }
   
public void OnDestroy() public void OnDestroy()
{ {
foreach (IVOID_Module module in this.Modules) foreach (IVOID_Module module in this.modules)
{ {
if (module is IVOID_BehaviorModule) if (module is IVOID_BehaviorModule)
{ {
((IVOID_BehaviorModule)module).OnDestroy(); ((IVOID_BehaviorModule)module).OnDestroy();
} }
} }
   
this.Dispose(); this.Dispose();
} }
   
public virtual void OnApplicationQuit() public virtual void OnApplicationQuit()
{ {
if (this.onApplicationQuit != null) if (this.onApplicationQuit != null)
{ {
this.onApplicationQuit(this); this.onApplicationQuit(this);
} }
   
this.OnDestroy(); this.OnDestroy();
} }
   
  public override void StartGUI()
  {
  if (!this.GUIRunning)
  {
  RenderingManager.AddToPostDrawQueue(3, this.DrawGUI);
  }
  }
   
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 override void ModuleWindow(int id)
{ {
GUILayout.BeginVertical(); GUILayout.BeginVertical();
   
if (this.powerAvailable || !HighLogic.LoadedSceneIsFlight) if (this.powerAvailable || !HighLogic.LoadedSceneIsFlight)
{ {
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);  
} }
} }
   
if (togglePower || !HighLogic.LoadedSceneIsFlight) if (togglePower || !HighLogic.LoadedSceneIsFlight)
{ {
foreach (IVOID_Module module in this.Modules) foreach (IVOID_Module module in this.modules)
{ {
module.toggleActive = GUITools.Toggle(module.toggleActive, module.Name); if (module is VOID_ConfigWindow)
  {
  continue;
  }
   
  module.Active = GUITools.Toggle(module.Active, module.Name);
} }
} }
} }
else else
{ {
GUILayout.Label("-- POWER LOST --", VOID_Styles.labelRed); GUILayout.Label("-- POWER LOST --", VOID_Styles.labelRed);
} }
   
this.configWindowMinimized.value = !GUITools.Toggle(!this.configWindowMinimized, "Configuration"); VOID_ConfigWindow.Instance.Active = GUITools.Toggle(
  VOID_ConfigWindow.Instance.Active,
  "Configuration"
  );
   
GUILayout.EndVertical(); GUILayout.EndVertical();
GUI.DragWindow();  
} base.ModuleWindow(id);
   
public void VOIDConfigWindow(int _)  
{  
GUILayout.BeginVertical();  
   
this.DrawConfigurables();  
   
GUILayout.EndVertical();  
GUI.DragWindow();  
} }
   
public override void DrawConfigurables() public override void DrawConfigurables()
{ {
GUIContent _content; GUIContent _content;
   
this.UseToolbarManager = GUITools.Toggle(this.UseToolbarManager, "Use Blizzy's Toolbar If Available"); this.useToolbarManager = GUITools.Toggle(this.useToolbarManager, "Use Blizzy's Toolbar If Available");
   
this.vesselSimActive.value = GUITools.Toggle(this.vesselSimActive.value, this.vesselSimActive.value = GUITools.Toggle(this.vesselSimActive.value,
"Enable Engineering Calculations"); "Enable Engineering Calculations");
   
  bool useEarthTime = (this.TimeScale & VOID_TimeScale.KERBIN_TIME) == 0u;
  bool useSiderealTime = (this.TimeScale & VOID_TimeScale.SOLAR_DAY) == 0u;
  bool useRoundedScale = (this.TimeScale & VOID_TimeScale.ROUNDED_SCALE) != 0u;
   
  useEarthTime = GUITools.Toggle(useEarthTime, "Use Earth Time (changes KSP option)");
   
  GameSettings.KERBIN_TIME = !useEarthTime;
   
  useSiderealTime = GUITools.Toggle(
  useSiderealTime,
  string.Format(
  "Time Scale: {0}",
  useSiderealTime ? "Sidereal" : "Solar"
  )
  );
   
  useRoundedScale = GUITools.Toggle(
  useRoundedScale,
  string.Format(
  "Time Scale: {0}",
  useRoundedScale ? "Rounded" : "True"
  )
  );
   
  if (useEarthTime)
  {
  this.TimeScale &= ~VOID_TimeScale.KERBIN_TIME;
  }
  else
  {
  this.TimeScale |= VOID_TimeScale.KERBIN_TIME;
  }
   
  if (useSiderealTime)
  {
  this.TimeScale &= ~VOID_TimeScale.SOLAR_DAY;
  }
  else
  {
  this.TimeScale |= VOID_TimeScale.SOLAR_DAY;
  }
   
  if (useRoundedScale)
  {
  this.TimeScale |= VOID_TimeScale.ROUNDED_SCALE;
  }
  else
  {
  this.TimeScale &= ~VOID_TimeScale.ROUNDED_SCALE;
  }
   
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.value = 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 = GUITools.Toggle(this.factoryReset, "Factory Reset"); this.FactoryReset = GUITools.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.");  
   
this.Stages = SimManager.Stages;  
   
if (this.Stages != null)  
{  
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 = new TimeSpan(0, 0, 0, 0, (int)(this.updatePeriod * 1000d)); SimManager.minSimTime = new TimeSpan(0, 0, 0, 0, (int)(this.UpdatePeriod * 1000d));
   
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 GetSimManagerResults()
  {
  Tools.PostDebugMessage(this, "VesselSimulator results ready, setting Stages.");
   
  this.Stages = SimManager.Stages;
   
  if (this.Stages != null)
  {
  this.LastStage = this.Stages.Last();
  }
} }
   
protected void LoadModulesOfType<U>() protected void LoadModulesOfType<U>()
{ {
Tools.DebugLogger sb = Tools.DebugLogger.New(this); Tools.DebugLogger sb = Tools.DebugLogger.New(this);
sb.AppendLine("Loading modules..."); sb.AppendLine("Loading modules...");
   
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(U).IsAssignableFrom(loadedType) || !typeof(U).IsAssignableFrom(loadedType) ||
typeof(VOIDCore).IsAssignableFrom(loadedType) typeof(VOIDCore).IsAssignableFrom(loadedType)
) )
{ {
continue; continue;
} }
   
sb.AppendFormat("Checking IVOID_Module type {0}...", loadedType.Name); sb.AppendFormat("Checking IVOID_Module type {0}...", loadedType.Name);
   
GameScenes[] validScenes = null;  
   
foreach (var attr in loadedType.GetCustomAttributes(true))  
{  
if (attr is VOID_ScenesAttribute)  
{  
validScenes = ((VOID_ScenesAttribute)attr).ValidScenes;  
   
sb.Append("VOID_ScenesAttribute found;");  
   
break;  
}  
}  
   
if (validScenes == null)  
{  
validScenes = new GameScenes[] { GameScenes.FLIGHT };  
   
   
sb.Append("VOID_ScenesAttribute not found;");  
   
}  
   
sb.AppendFormat(  
" validScenes set to {0}.",  
string.Join(  
", ",  
validScenes.Select(s => Enum.GetName(typeof(GameScenes), s)).ToArray()  
)  
);  
   
if (!validScenes.Contains(HighLogic.LoadedScene))  
{  
sb.AppendFormat(" {0} not found in validScenes, skipping.",  
Enum.GetName(typeof(GameScenes), HighLogic.LoadedScene));  
continue;  
}  
   
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}\n", ex.GetType().Name); sb.AppendFormat("Failed, caught {0}\n", ex.GetType().Name);
   
#if DEBUG #if DEBUG
Debug.LogException(ex); Debug.LogException(ex);
#endif #endif
} }
} }
} }
   
this._modulesLoaded = true; this.modulesLoaded = true;
   
sb.AppendFormat("Loaded {0} modules.\n", this.Modules.Count); sb.AppendFormat("Loaded {0} modules.\n", this.Modules.Count);
   
sb.Print(); sb.Print();
} }
   
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;
} }
   
var InstanceProperty = T.GetProperty( var InstanceProperty = T.GetProperty(
"Instance", "Instance",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public System.Reflection.BindingFlags.Static |
  System.Reflection.BindingFlags.Public |
  System.Reflection.BindingFlags.FlattenHierarchy
); );
   
object modInstance = null; object modInstance = null;
IVOID_Module module; IVOID_Module module;
   
if (InstanceProperty != null) if (InstanceProperty != null)
{ {
modInstance = InstanceProperty.GetValue(null, null); modInstance = InstanceProperty.GetValue(null, null);
} }
   
if (modInstance != null) if (modInstance != null)
{ {
module = modInstance as IVOID_Module; module = modInstance as IVOID_Module;
} }
else else
{ {
module = Activator.CreateInstance(T) as IVOID_Module; module = Activator.CreateInstance(T) as IVOID_Module;
} }
   
module.LoadConfig(); if (module.InValidGame && module.InValidScene)
this._modules.Add(module); {
  module.LoadConfig();
Tools.PostDebugMessage(string.Format( this.modules.Add(module);
"{0}: loaded module {1}.",  
this.GetType().Name, Tools.PostDebugMessage(string.Format(
T.Name "{0}: loaded module {1}.",
)); this.GetType().Name,
  T.Name
  ));
  }
  else
  {
  if (module is IDisposable)
  {
  (module as IDisposable).Dispose();
  }
  }
} }
   
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();
   
if (this.onSkinChanged != null) if (this.onSkinChanged != null)
{ {
this.onSkinChanged(this); this.onSkinChanged(this);
} }
   
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>().ToArray();
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.Visible = true; this.ToolbarButton.Visible = true;
   
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.Active = !this.Active;
this.SetIconTexture(this.powerState | this.activeState); }
   
  protected void SetIconTexture()
  {
  if (
  this.iconState != (this.powerState | this.activeState) ||
  (this.VOIDIconTexture == null && this.AppLauncherButton != null)
  )
  {
  this.iconState = this.powerState | this.activeState;
   
  this.SetIconTexture(this.iconState);
  }
} }
   
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 (texturePath == null)
  {
  return;
  }
   
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);  
   
if (this.AppLauncherButton != null) if (this.AppLauncherButton != null)
{ {
  this.VOIDIconTexture = GameDatabase.Instance.GetTexture(texturePath.Replace("icon", "appIcon"), false);
   
this.AppLauncherButton.SetTexture(VOIDIconTexture); this.AppLauncherButton.SetTexture(VOIDIconTexture);
} }
} }
   
protected virtual void CheckAndSave() protected virtual 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();
} }
   
  this.TimeScale |= GameSettings.KERBIN_TIME ? VOID_TimeScale.KERBIN_TIME : 0u;
} }
   
public override void SaveConfig() public override void SaveConfig()
{ {
if (this.configNeedsUpdate && this is VOIDCore_Flight) if (this.configNeedsUpdate && this is VOIDCore_Flight)
{ {
KSP.IO.File.Delete<T>("config.xml"); KSP.IO.File.Delete<T>("config.xml");
} }
   
var config = KSP.IO.PluginConfiguration.CreateForType<T>(); var config = KSP.IO.PluginConfiguration.CreateForType<T>();
   
config.load(); config.load();
   
this._SaveToConfig(config); this.Save(config);
   
foreach (IVOID_Module module in this.Modules) foreach (IVOID_Module module in this.modules)
{ {
module._SaveToConfig(config); module.Save(config);
} }
   
config.save(); config.save();
   
this.configDirty = false; this.configDirty = false;
} }
   
public VOIDCore_Generic() public VOIDCore_Generic()
{ {
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.Name = string.Format("VOID {0}", this.VoidVersion.ToString());
   
this.powerAvailable = true; this.powerAvailable = true;
   
this.toggleActive = true; this.Active = true;
   
this._skinName = this.defaultSkin; this.skinName = (VOID_SaveValue<string>)this.defaultSkin;
this._skinIdx = int.MinValue; this.skinIdx = int.MinValue;
   
this.VOIDIconOnActivePath = "VOID/Textures/void_icon_light_glow"; this.VOIDIconOnActivePath = "VOID/Textures/void_icon_light_glow";
this.VOIDIconOnInactivePath = "VOID/Textures/void_icon_dark_glow"; this.VOIDIconOnInactivePath = "VOID/Textures/void_icon_dark_glow";
this.VOIDIconOffActivePath = "VOID/Textures/void_icon_light"; this.VOIDIconOffActivePath = "VOID/Textures/void_icon_light";
this.VOIDIconOffInactivePath = "VOID/Textures/void_icon_dark"; this.VOIDIconOffInactivePath = "VOID/Textures/void_icon_dark";
   
this.saveTimer = 0f; this.saveTimer = 0f;
this.updateTimer = 0f; this.UpdateTimer = 0f;
   
this.vesselSimActive = true; this.vesselSimActive = (VOID_SaveValue<bool>)true;
  SimManager.Atmosphere = 0d;
this.UseToolbarManager = ToolbarManager.ToolbarAvailable; SimManager.OnReady += this.GetSimManagerResults;
   
  this.useToolbarManager = ToolbarManager.ToolbarAvailable;
   
this.LoadConfig(); this.LoadConfig();
   
this._configVersion = VOIDCore.CONFIG_VERSION; this.configVersion = (VOID_SaveValue<int>)VOIDCore.CONFIG_VERSION;
   
this.SetIconTexture(this.powerState | this.activeState); this.FactoryReset = false;
  }
this.factoryReset = false;  
} public override void Dispose()
   
public virtual void Dispose()  
{ {
this.StopGUI(); this.StopGUI();
   
  this.onSkinChanged(this);
   
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;
} }
   
_instance = null; _instance = null;
_initialized = false; _initialized = false;
} }
   
protected enum IconState  
{  
PowerOff = 1,  
PowerOn = 2,  
Inactive = 4,  
Active = 8  
}  
} }
} }
   
   
// VOID // VOID
// //
// VOIDCore_SpaceCentre.cs // VOIDCore_SpaceCentre.cs
// //
// Copyright © 2015, toadicus // Copyright © 2015, 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 System; using System;
   
namespace VOID namespace VOID
{ {
[VOID_Scenes(GameScenes.SPACECENTER)] [VOID_Scenes(GameScenes.SPACECENTER)]
public class VOIDCore_SpaceCentre : VOIDCore_Generic<VOIDCore_SpaceCentre> public class VOIDCore_SpaceCentre : VOIDCore_Generic<VOIDCore_SpaceCentre>
{ {
public VOIDCore_SpaceCentre() : base()  
{  
base.Name = "VOID Core: SpaceCentre";  
}  
   
public override void FixedUpdate() {} public override void FixedUpdate() {}
} }
} }
   
   
// VOID // VOID
// //
// VOID_CBInfoBrowser.cs // VOID_CBInfoBrowser.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.Collections.Generic; using System.Collections.Generic;
using ToadicusTools; using ToadicusTools;
using UnityEngine; using UnityEngine;
   
namespace VOID namespace VOID
{ {
public class VOID_CBInfoBrowser : VOID_WindowModule public class VOID_CBInfoBrowser : VOID_WindowModule
{ {
[AVOID_SaveValue("selectedBodyIdx1")] [AVOID_SaveValue("selectedBodyIdx1")]
protected VOID_SaveValue<int> selectedBodyIdx1 = 1; protected VOID_SaveValue<int> selectedBodyIdx1;
   
[AVOID_SaveValue("selectedBodyIdx2")] [AVOID_SaveValue("selectedBodyIdx2")]
protected VOID_SaveValue<int> selectedBodyIdx2 = 2; protected VOID_SaveValue<int> selectedBodyIdx2;
   
protected CelestialBody selectedBody1; protected CelestialBody selectedBody1;
protected CelestialBody selectedBody2; protected CelestialBody selectedBody2;
   
[AVOID_SaveValue("toggleOrbital")] [AVOID_SaveValue("toggleOrbital")]
protected VOID_SaveValue<bool> toggleOrbital = false; protected VOID_SaveValue<bool> toggleOrbital;
   
[AVOID_SaveValue("togglePhysical")] [AVOID_SaveValue("togglePhysical")]
protected VOID_SaveValue<bool> togglePhysical = false; protected VOID_SaveValue<bool> togglePhysical;
   
[AVOID_SaveValue("toggleScience")] [AVOID_SaveValue("toggleScience")]
protected VOID_SaveValue<bool> toggleScience = false; protected VOID_SaveValue<bool> toggleScience;
   
public VOID_CBInfoBrowser() public VOID_CBInfoBrowser()
{ {
this.Name = "Celestial Body Information Browser"; this.Name = "Celestial Body Information Browser";
   
this.WindowPos.x = 10; this.WindowPos.x = 10;
this.WindowPos.y = 85; this.WindowPos.y = 85;
   
  this.selectedBodyIdx1 = (VOID_SaveValue<int>)1;
  this.selectedBodyIdx2 = (VOID_SaveValue<int>)2;
   
  this.toggleOrbital = (VOID_SaveValue<bool>)false;
  this.togglePhysical = (VOID_SaveValue<bool>)false;
  this.toggleScience = (VOID_SaveValue<bool>)false;
} }
   
public override void ModuleWindow(int _) public override void ModuleWindow(int id)
{ {
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
   
GUILayout.BeginVertical(GUILayout.Width(150)); GUILayout.BeginVertical(GUILayout.Width(150));
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("", GUILayout.ExpandWidth(true)); GUILayout.Label("", GUILayout.ExpandWidth(true));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.EndVertical(); GUILayout.EndVertical();
   
GUILayout.BeginVertical(GUILayout.Width(150)); GUILayout.BeginVertical(GUILayout.Width(150));
   
selectedBody1 = this.core.allBodies[selectedBodyIdx1]; selectedBody1 = this.core.AllBodies[selectedBodyIdx1];
selectedBody2 = this.core.allBodies[selectedBodyIdx2]; selectedBody2 = this.core.AllBodies[selectedBodyIdx2];
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
if (GUILayout.Button("<", GUILayout.ExpandWidth(false))) if (GUILayout.Button("<", GUILayout.ExpandWidth(false)))
{ {
selectedBodyIdx1--; selectedBodyIdx1.value--;
if (selectedBodyIdx1 < 0) selectedBodyIdx1 = this.core.allBodies.Count - 1; if (selectedBodyIdx1 < 0)
} {
GUILayout.Label(this.core.allBodies[selectedBodyIdx1].bodyName, VOID_Styles.labelCenterBold, GUILayout.ExpandWidth(true)); selectedBodyIdx1.value = this.core.AllBodies.Count - 1;
  }
  }
  GUILayout.Label(this.core.AllBodies[selectedBodyIdx1].bodyName, VOID_Styles.labelCenterBold, GUILayout.ExpandWidth(true));
if (GUILayout.Button(">", GUILayout.ExpandWidth(false))) if (GUILayout.Button(">", GUILayout.ExpandWidth(false)))
{ {
selectedBodyIdx1++; selectedBodyIdx1.value++;
if (selectedBodyIdx1 > this.core.allBodies.Count - 1) selectedBodyIdx1 = 0; if (selectedBodyIdx1 > this.core.AllBodies.Count - 1)
  {
  selectedBodyIdx1.value = 0;
  }
} }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUILayout.EndVertical(); GUILayout.EndVertical();
   
GUILayout.BeginVertical(GUILayout.Width(150)); GUILayout.BeginVertical(GUILayout.Width(150));
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
if (GUILayout.Button("<", GUILayout.ExpandWidth(false))) if (GUILayout.Button("<", GUILayout.ExpandWidth(false)))
{ {
selectedBodyIdx2--; selectedBodyIdx2.value--;
if (selectedBodyIdx2 < 0) selectedBodyIdx2 = this.core.allBodies.Count - 1; if (selectedBodyIdx2 < 0)
} {
GUILayout.Label(this.core.allBodies[selectedBodyIdx2].bodyName, VOID_Styles.labelCenterBold, GUILayout.ExpandWidth(true)); selectedBodyIdx2.value = this.core.AllBodies.Count - 1;
  }
  }
  GUILayout.Label(this.core.AllBodies[selectedBodyIdx2].bodyName, VOID_Styles.labelCenterBold, GUILayout.ExpandWidth(true));
if (GUILayout.Button(">", GUILayout.ExpandWidth(false))) if (GUILayout.Button(">", GUILayout.ExpandWidth(false)))
{ {
selectedBodyIdx2++; selectedBodyIdx2.value++;
if (selectedBodyIdx2 > this.core.allBodies.Count - 1) selectedBodyIdx2 = 0; if (selectedBodyIdx2 > this.core.AllBodies.Count - 1)
  {
  selectedBodyIdx2.value = 0;
  }
} }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUILayout.EndVertical(); GUILayout.EndVertical();
   
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
//toggle for orbital info chunk //toggle for orbital info chunk
if (GUILayout.Button("Orbital Characteristics", GUILayout.ExpandWidth(true))) toggleOrbital.value = !toggleOrbital; if (GUILayout.Button("Orbital Characteristics", GUILayout.ExpandWidth(true))) toggleOrbital.value = !toggleOrbital;
   
if (toggleOrbital) if (toggleOrbital)
{ {
//begin orbital into horizontal chunk //begin orbital into horizontal chunk
//print("begin orbital info section..."); //print("begin orbital info section...");
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
   
//begin orbital value labels column //begin orbital value labels column
GUILayout.BeginVertical(GUILayout.Width(150)); GUILayout.BeginVertical(GUILayout.Width(150));
   
//print("printing row labels..."); //print("printing row labels...");
   
GUILayout.Label("Apoapsis:"); GUILayout.Label("Apoapsis:");
GUILayout.Label("Time to Ap:"); GUILayout.Label("Time to Ap:");
GUILayout.Label("Periapsis:"); GUILayout.Label("Periapsis:");
GUILayout.Label("Time to Pe:"); GUILayout.Label("Time to Pe:");
GUILayout.Label("Semi-major axis:"); GUILayout.Label("Semi-major axis:");
GUILayout.Label("Eccentricity:"); GUILayout.Label("Eccentricity:");
GUILayout.Label("Orbital period:"); GUILayout.Label("Orbital period:");
GUILayout.Label("Rotational period:"); GUILayout.Label("Rotational period:");
GUILayout.Label("Velocity:"); GUILayout.Label("Velocity:");
GUILayout.Label("Mean anomaly:"); GUILayout.Label("Mean anomaly:");
GUILayout.Label("True anomaly:"); GUILayout.Label("True anomaly:");
GUILayout.Label("Eccentric anomaly:"); GUILayout.Label("Eccentric anomaly:");
GUILayout.Label("Inclination:"); GUILayout.Label("Inclination:");
GUILayout.Label("Long. ascending node:"); GUILayout.Label("Long. ascending node:");
GUILayout.Label("Arg. of periapsis:"); GUILayout.Label("Arg. of periapsis:");
GUILayout.Label("Tidally locked:"); GUILayout.Label("Tidally locked:");
   
//end orbital value labels column //end orbital value labels column
GUILayout.EndVertical(); GUILayout.EndVertical();
   
//begin primary orbital values column //begin primary orbital values column
GUILayout.BeginVertical(GUILayout.Width(150)); GUILayout.BeginVertical(GUILayout.Width(150));
   
body_OP_show_orbital_info(selectedBody1); body_OP_show_orbital_info(selectedBody1);
   
//end primary orbital values column //end primary orbital values column
GUILayout.EndVertical(); GUILayout.EndVertical();
   
//begin secondary orbital values column //begin secondary orbital values column
GUILayout.BeginVertical(GUILayout.Width(150)); GUILayout.BeginVertical(GUILayout.Width(150));
   
body_OP_show_orbital_info(selectedBody2); body_OP_show_orbital_info(selectedBody2);
   
//end secondary orbital values column //end secondary orbital values column
GUILayout.EndVertical(); GUILayout.EndVertical();
   
//end orbital info horizontal chunk //end orbital info horizontal chunk
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
   
//toggle for physical info chunk //toggle for physical info chunk
if (GUILayout.Button("Physical Characteristics", GUILayout.ExpandWidth(true))) togglePhysical.value = !togglePhysical; if (GUILayout.Button("Physical Characteristics", GUILayout.ExpandWidth(true))) togglePhysical.value = !togglePhysical;
   
if (togglePhysical) if (togglePhysical)
{ {
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
   
//begin physical info value label column //begin physical info value label column
GUILayout.BeginVertical(GUILayout.Width(150)); GUILayout.BeginVertical(GUILayout.Width(150));
   
GUILayout.Label("Radius:"); GUILayout.Label("Radius:");
GUILayout.Label("Surface area:"); GUILayout.Label("Surface area:");
GUILayout.Label("Volume:"); GUILayout.Label("Volume:");
GUILayout.Label("Mass:"); GUILayout.Label("Mass:");
GUILayout.Label("Density:"); GUILayout.Label("Density:");
GUILayout.Label("Sphere of influence:"); GUILayout.Label("Sphere of influence:");
GUILayout.Label("Natural satellites:"); GUILayout.Label("Natural satellites:");
GUILayout.Label("Artificial satellites:"); GUILayout.Label("Artificial satellites:");
GUILayout.Label("Surface gravity:"); GUILayout.Label("Surface gravity:");
GUILayout.Label("Atmosphere altitude:"); GUILayout.Label("Atmosphere altitude:");
GUILayout.Label("Atmospheric O\u2082:"); GUILayout.Label("Atmospheric O\u2082:");
GUILayout.Label("Has ocean:"); GUILayout.Label("Has ocean:");
   
//end physical info value label column //end physical info value label column
GUILayout.EndVertical(); GUILayout.EndVertical();
   
//begin primary physical values column //begin primary physical values column
GUILayout.BeginVertical(GUILayout.Width(150)); GUILayout.BeginVertical(GUILayout.Width(150));
   
body_OP_show_physical_info(selectedBody1); body_OP_show_physical_info(selectedBody1);
   
//end primary physical column //end primary physical column
GUILayout.EndVertical(); GUILayout.EndVertical();
   
//begin secondary physical values column //begin secondary physical values column
GUILayout.BeginVertical(GUILayout.Width(150)); GUILayout.BeginVertical(GUILayout.Width(150));
   
body_OP_show_physical_info(selectedBody2); body_OP_show_physical_info(selectedBody2);
   
//end target physical values column //end target physical values column
GUILayout.EndVertical(); GUILayout.EndVertical();
   
//end physical value horizontal chunk //end physical value horizontal chunk
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
   
if (GUILayout.Button("Scientific Parameters", GUILayout.ExpandWidth(true))) if (GUILayout.Button("Scientific Parameters", GUILayout.ExpandWidth(true)))
{ {
toggleScience.value = !toggleScience; toggleScience.value = !toggleScience;
} }
   
if (toggleScience) if (toggleScience)
{ {
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
   
//begin physical info value label column //begin physical info value label column
GUILayout.BeginVertical(GUILayout.Width(150)); GUILayout.BeginVertical(GUILayout.Width(150));
   
   
/* /*
* public float RecoveryValue = 1f; * public float RecoveryValue = 1f;
   
public float InSpaceHighDataValue = 1f; public float InSpaceHighDataValue = 1f;
   
public float spaceAltitudeThreshold = 250000f; public float spaceAltitudeThreshold = 250000f;
   
public float flyingAltitudeThreshold = 18000f; public float flyingAltitudeThreshold = 18000f;
   
public float InSpaceLowDataValue = 1f; public float InSpaceLowDataValue = 1f;
   
public float SplashedDataValue = 1f; public float SplashedDataValue = 1f;
   
public float LandedDataValue = 1f; public float LandedDataValue = 1f;
   
public float FlyingHighDataValue = 1f; public float FlyingHighDataValue = 1f;
   
public float FlyingLowDataValue = 1f; public float FlyingLowDataValue = 1f;
*/ */
   
GUILayout.Label("Surface Multiplier:"); GUILayout.Label("Surface Multiplier:");
GUILayout.Label("Ocean Multiplier:"); GUILayout.Label("Ocean Multiplier:");
GUILayout.Label("Flying-Low Multiplier:"); GUILayout.Label("Flying-Low Multiplier:");
GUILayout.Label("Flying-High Multiplier:"); GUILayout.Label("Flying-High Multiplier:");
GUILayout.Label("Low Orbit Multiplier:"); GUILayout.Label("Low Orbit Multiplier:");
GUILayout.Label("High Orbit Multiplier:"); GUILayout.Label("High Orbit Multiplier:");
GUILayout.Label("'Flying-High' Altitude:"); GUILayout.Label("'Flying-High' Altitude:");
GUILayout.Label("'High Orbit' Altitude:"); GUILayout.Label("'High Orbit' Altitude:");
GUILayout.Label("Recovery Multiplier:"); GUILayout.Label("Recovery Multiplier:");
   
//end physical info value label column //end physical info value label column
GUILayout.EndVertical(); GUILayout.EndVertical();
   
//begin primary physical values column //begin primary physical values column
GUILayout.BeginVertical(GUILayout.Width(150)); GUILayout.BeginVertical(GUILayout.Width(150));
   
this.cbColumnScience(selectedBody1); this.cbColumnScience(selectedBody1);
   
//end primary physical column //end primary physical column
GUILayout.EndVertical(); GUILayout.EndVertical();
   
//begin secondary physical values column //begin secondary physical values column
GUILayout.BeginVertical(GUILayout.Width(150)); GUILayout.BeginVertical(GUILayout.Width(150));
   
this.cbColumnScience(selectedBody2); this.cbColumnScience(selectedBody2);
   
//end target physical values column //end target physical values column
GUILayout.EndVertical(); GUILayout.EndVertical();
   
//end physical value horizontal chunk //end physical value horizontal chunk
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
   
GUI.DragWindow(); base.ModuleWindow(id);
} }
   
private void body_OP_show_orbital_info(CelestialBody body) private void body_OP_show_orbital_info(CelestialBody body)
{ {
if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
else GUILayout.Label((body.orbit.ApA / 1000).ToString("##,#") + "km", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); else GUILayout.Label((body.orbit.ApA / 1000).ToString("##,#") + "km", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
   
if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
else GUILayout.Label(VOID_Tools.FormatInterval(body.orbit.timeToAp), VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); else GUILayout.Label(VOID_Tools.FormatInterval(body.orbit.timeToAp), VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
   
if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
else GUILayout.Label((body.orbit.PeA / 1000).ToString("##,#") + "km", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); else GUILayout.Label((body.orbit.PeA / 1000).ToString("##,#") + "km", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
   
if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
else GUILayout.Label(VOID_Tools.FormatInterval(body.orbit.timeToPe), VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); else GUILayout.Label(VOID_Tools.FormatInterval(body.orbit.timeToPe), VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
   
if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
else GUILayout.Label((body.orbit.semiMajorAxis / 1000).ToString("##,#") + "km", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); else GUILayout.Label((body.orbit.semiMajorAxis / 1000).ToString("##,#") + "km", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
   
if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
else GUILayout.Label(body.orbit.eccentricity.ToString("F4") + "", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); else GUILayout.Label(body.orbit.eccentricity.ToString("F4") + "", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
   
if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
else GUILayout.Label(VOID_Tools.FormatInterval(body.orbit.period), VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); else GUILayout.Label(VOID_Tools.FormatInterval(body.orbit.period), VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
   
if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
else GUILayout.Label(VOID_Tools.FormatInterval(body.rotationPeriod), VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); else GUILayout.Label(VOID_Tools.FormatInterval(body.rotationPeriod), VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
   
if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
else GUILayout.Label((body.orbit.orbitalSpeed / 1000).ToString("F2") + "km/s", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); else GUILayout.Label((body.orbit.orbitalSpeed / 1000).ToString("F2") + "km/s", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
   
// Toadicus edit: convert mean anomaly into degrees. // Toadicus edit: convert mean anomaly into degrees.
if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
else GUILayout.Label((body.orbit.meanAnomaly * 180d / Math.PI).ToString("F3") + "°", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); else GUILayout.Label((body.orbit.meanAnomaly * 180d / Math.PI).ToString("F3") + "°", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
   
if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
else GUILayout.Label(body.orbit.trueAnomaly.ToString("F3") + "°", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); else GUILayout.Label(body.orbit.trueAnomaly.ToString("F3") + "°", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
   
// Toadicus edit: convert eccentric anomaly into degrees. // Toadicus edit: convert eccentric anomaly into degrees.
if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
else GUILayout.Label((body.orbit.eccentricAnomaly * 180d / Math.PI).ToString("F3") + "°", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); else GUILayout.Label((body.orbit.eccentricAnomaly * 180d / Math.PI).ToString("F3") + "°", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
   
if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
else GUILayout.Label(body.orbit.inclination.ToString("F3") + "°", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); else GUILayout.Label(body.orbit.inclination.ToString("F3") + "°", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
   
if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
else GUILayout.Label(body.orbit.LAN.ToString("F3") + "°", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); else GUILayout.Label(body.orbit.LAN.ToString("F3") + "°", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
   
if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
else GUILayout.Label(body.orbit.argumentOfPeriapsis.ToString("F3") + "°", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); else GUILayout.Label(body.orbit.argumentOfPeriapsis.ToString("F3") + "°", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
   
if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
else else
{ {
string body_tidally_locked = "No"; string body_tidally_locked = "No";
if (body.tidallyLocked) body_tidally_locked = "Yes"; if (body.tidallyLocked) body_tidally_locked = "Yes";
GUILayout.Label(body_tidally_locked, VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); GUILayout.Label(body_tidally_locked, VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
} }
} }
   
private void body_OP_show_physical_info(CelestialBody body) private void body_OP_show_physical_info(CelestialBody body)
{ {
   
GUILayout.Label((body.Radius / 1000).ToString("##,#") + "km", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); GUILayout.Label((body.Radius / 1000).ToString("##,#") + "km", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
   
GUILayout.Label((((body.Radius * body.Radius) * 4 * Math.PI) / 1000).ToString("0.00e+00") + "km²", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); GUILayout.Label((((body.Radius * body.Radius) * 4 * Math.PI) / 1000).ToString("0.00e+00") + "km²", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
   
// divide by 1000 to convert m to km // divide by 1000 to convert m to km
GUILayout.Label((((4d / 3) * Math.PI * (body.Radius * body.Radius * body.Radius)) / 1000).ToString("0.00e+00") + "km³", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); GUILayout.Label((((4d / 3) * Math.PI * (body.Radius * body.Radius * body.Radius)) / 1000).ToString("0.00e+00") + "km³", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
   
GUILayout.Label(body.Mass.ToString("0.00e+00") + "kg", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); GUILayout.Label(body.Mass.ToString("0.00e+00") + "kg", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
   
double p = body.Mass / ((body.Radius * body.Radius * body.Radius) * (4d / 3) * Math.PI); double p = body.Mass / ((body.Radius * body.Radius * body.Radius) * (4d / 3) * Math.PI);
   
GUILayout.Label(p.ToString("##,#") + "kg/m³", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); GUILayout.Label(p.ToString("##,#") + "kg/m³", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
   
if (body.bodyName == "Sun") GUILayout.Label(Tools.MuMech_ToSI(body.sphereOfInfluence), VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label(Tools.MuMech_ToSI(body.sphereOfInfluence), VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
else GUILayout.Label(Tools.MuMech_ToSI(body.sphereOfInfluence), VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); else GUILayout.Label(Tools.MuMech_ToSI(body.sphereOfInfluence), VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
   
GUILayout.Label(body.orbitingBodies.Count.ToString(), VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); GUILayout.Label(body.orbitingBodies.Count.ToString(), VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
   
//show # artificial satellites //show # artificial satellites
int num_art_sats = 0; int num_art_sats = 0;
foreach (Vessel v in FlightGlobals.Vessels) foreach (Vessel v in FlightGlobals.Vessels)
{ {
if (v.mainBody == body && v.situation.ToString() == "ORBITING") num_art_sats++; if (v.mainBody == body && v.situation.ToString() == "ORBITING") num_art_sats++;
} }
   
GUILayout.Label(num_art_sats.ToString(), VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); GUILayout.Label(num_art_sats.ToString(), VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
   
double g_ASL = (VOIDCore.Constant_G * body.Mass) / (body.Radius * body.Radius); double g_ASL = (VOIDCore.Constant_G * body.Mass) / (body.Radius * body.Radius);
   
GUILayout.Label(Tools.MuMech_ToSI(g_ASL) + "m/s²", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); GUILayout.Label(Tools.MuMech_ToSI(g_ASL) + "m/s²", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
   
if (body.atmosphere) if (body.atmosphere)
{ {
GUILayout.Label("≈ " + Tools.MuMech_ToSI(body.maxAtmosphereAltitude) + "m", GUILayout.Label("≈ " + Tools.MuMech_ToSI(body.maxAtmosphereAltitude) + "m",
VOID_Styles.labelRight, VOID_Styles.labelRight,
GUILayout.ExpandWidth(true)); GUILayout.ExpandWidth(true));
   
string O2 = "No"; string O2 = "No";
if (body.atmosphereContainsOxygen == true) O2 = "Yes"; if (body.atmosphereContainsOxygen == true) O2 = "Yes";
GUILayout.Label(O2, VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); GUILayout.Label(O2, VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
} }
else else
{ {
GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
} }
   
string ocean = "No"; string ocean = "No";
if (body.ocean == true) ocean = "Yes"; if (body.ocean == true) ocean = "Yes";
GUILayout.Label(ocean, VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); GUILayout.Label(ocean, VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
} }
   
private void cbColumnScience(CelestialBody body) private void cbColumnScience(CelestialBody body)
{ {
/*GUILayout.Label("Surface Science Multiplier:"); /*GUILayout.Label("Surface Science Multiplier:");
GUILayout.Label("Ocean Science Multiplier:"); GUILayout.Label("Ocean Science Multiplier:");
GUILayout.Label("Low-Atmosphere Science Multiplier:"); GUILayout.Label("Low-Atmosphere Science Multiplier:");
GUILayout.Label("High-Atmosphere Science Multiplier:"); GUILayout.Label("High-Atmosphere Science Multiplier:");
GUILayout.Label("Low Orbit Science Multiplier:"); GUILayout.Label("Low Orbit Science Multiplier:");
GUILayout.Label("High Orbit Science Multiplier:"); GUILayout.Label("High Orbit Science Multiplier:");
GUILayout.Label("'In Space' Altitude:"); GUILayout.Label("'In Space' Altitude:");
GUILayout.Label("'Flying' Altitude:"); GUILayout.Label("'Flying' Altitude:");
GUILayout.Label("Recovery Multiplier:");*/ GUILayout.Label("Recovery Multiplier:");*/
   
var scienceValues = body.scienceValues; var scienceValues = body.scienceValues;
   
GUILayout.Label(scienceValues.LandedDataValue.ToString("0.0#"), GUILayout.Label(scienceValues.LandedDataValue.ToString("0.0#"),
VOID_Styles.labelRight, VOID_Styles.labelRight,
GUILayout.ExpandWidth(true)); GUILayout.ExpandWidth(true));
   
GUILayout.Label( GUILayout.Label(
body.ocean ? scienceValues.SplashedDataValue.ToString("0.0#") : "N/A", body.ocean ? scienceValues.SplashedDataValue.ToString("0.0#") : "N/A",
VOID_Styles.labelRight, VOID_Styles.labelRight,
GUILayout.ExpandWidth(true)); GUILayout.ExpandWidth(true));
   
GUILayout.Label( GUILayout.Label(
body.atmosphere ? scienceValues.FlyingLowDataValue.ToString("0.0#") : "N/A", body.atmosphere ? scienceValues.FlyingLowDataValue.ToString("0.0#") : "N/A",
VOID_Styles.labelRight, VOID_Styles.labelRight,
GUILayout.ExpandWidth(true)); GUILayout.ExpandWidth(true));
   
GUILayout.Label( GUILayout.Label(
body.atmosphere ? scienceValues.FlyingHighDataValue.ToString("0.0#") : "N/A", body.atmosphere ? scienceValues.FlyingHighDataValue.ToString("0.0#") : "N/A",
VOID_Styles.labelRight, VOID_Styles.labelRight,
GUILayout.ExpandWidth(true)); GUILayout.ExpandWidth(true));
   
GUILayout.Label(scienceValues.InSpaceLowDataValue.ToString("0.0#"), GUILayout.Label(scienceValues.InSpaceLowDataValue.ToString("0.0#"),
VOID_Styles.labelRight, VOID_Styles.labelRight,
GUILayout.ExpandWidth(true)); GUILayout.ExpandWidth(true));
   
GUILayout.Label(scienceValues.InSpaceHighDataValue.ToString("0.0#"), GUILayout.Label(scienceValues.InSpaceHighDataValue.ToString("0.0#"),
VOID_Styles.labelRight, VOID_Styles.labelRight,
GUILayout.ExpandWidth(true)); GUILayout.ExpandWidth(true));
   
GUILayout.Label( GUILayout.Label(
body.atmosphere ? scienceValues.flyingAltitudeThreshold.ToString("N0") : "N/A", body.atmosphere ? scienceValues.flyingAltitudeThreshold.ToString("N0") : "N/A",
VOID_Styles.labelRight, VOID_Styles.labelRight,
GUILayout.ExpandWidth(true)); GUILayout.ExpandWidth(true));
   
GUILayout.Label( GUILayout.Label(
scienceValues.spaceAltitudeThreshold.ToString("N0"), scienceValues.spaceAltitudeThreshold.ToString("N0"),
VOID_Styles.labelRight, VOID_Styles.labelRight,
GUILayout.ExpandWidth(true)); GUILayout.ExpandWidth(true));
   
GUILayout.Label(scienceValues.RecoveryValue.ToString("0.0#"), GUILayout.Label(scienceValues.RecoveryValue.ToString("0.0#"),
VOID_Styles.labelRight, VOID_Styles.labelRight,
GUILayout.ExpandWidth(true)); GUILayout.ExpandWidth(true));
} }
} }
} }
// 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
{ {
[VOID_Scenes(GameScenes.FLIGHT, GameScenes.EDITOR, GameScenes.SPACECENTER)] [VOID_Scenes(GameScenes.FLIGHT, GameScenes.EDITOR, GameScenes.SPACECENTER)]
[VOID_GameModes(Game.Modes.CAREER, Game.Modes.SCIENCE_SANDBOX)] [VOID_GameModes(Game.Modes.CAREER, Game.Modes.SCIENCE_SANDBOX)]
public class VOID_CareerStatus : VOID_WindowModule public class VOID_CareerStatus : VOID_SingletonWindow<VOID_CareerStatus>
{ {
public static VOID_CareerStatus Instance  
{  
get;  
private set;  
}  
   
public static string formatDelta(double delta, string numberFormat) public static string formatDelta(double delta, string numberFormat)
{ {
if (delta > 0) if (delta > 0)
{ {
return string.Format("<color='lime'>{0}↑</color>", delta.ToString(numberFormat, Tools.SIFormatter)); return string.Format("<color='lime'>{0}↑</color>", delta.ToString(numberFormat, Tools.SIFormatter));
} }
else if (delta < 0) else if (delta < 0)
{ {
return string.Format("<color='red'>{0}↓</color>", delta.ToString(numberFormat, Tools.SIFormatter)); return string.Format("<color='red'>{0}↓</color>", delta.ToString(numberFormat, Tools.SIFormatter));
} }
else else
{ {
return "0"; return "0";
} }
} }
   
public static string formatDelta(double delta) public static string formatDelta(double delta)
{ {
return formatDelta(delta, "#,##0.##"); return formatDelta(delta, "#,##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;
   
#pragma warning disable 0414 #pragma warning disable 0414
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;
#pragma warning restore 0414 #pragma warning restore 0414
   
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;
} }
   
private bool currenciesInitialized private bool currenciesInitialized
{ {
get get
{ {
Tools.PostDebugMessage( Tools.PostDebugMessage(
this, this,
"Checking init state:" + "Checking init state:" +
"\n\tcurrentFunds={0}" + "\n\tcurrentFunds={0}" +
"\n\tcurrentScience={1}" + "\n\tcurrentScience={1}" +
"\n\tcurrentReputation={2}", "\n\tcurrentReputation={2}",
this.currentFunds, this.currentFunds,
this.currentScience, this.currentScience,
this.currentReputation this.currentReputation
); );
   
return !( return !(
double.IsNaN(this.currentFunds) || double.IsNaN(this.currentFunds) ||
float.IsNaN(this.currentScience) || float.IsNaN(this.currentScience) ||
float.IsNaN(this.currentReputation) float.IsNaN(this.currentReputation)
); );
} }
} }
   
public override void DrawGUI() public override void DrawGUI()
{ {
if (Event.current.type != EventType.Layout && !this.currenciesInitialized) if (Event.current.type != EventType.Layout && !this.currenciesInitialized)
{ {
this.initCurrencies(); this.initCurrencies();
} }
   
base.DrawGUI(); base.DrawGUI();
} }
   
public override void ModuleWindow(int _) public override void ModuleWindow(int id)
{ {
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(true)); GUILayout.Label(this.fundsContent, GUILayout.ExpandWidth(true));
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(true)); GUILayout.Label(this.repContent, GUILayout.ExpandWidth(true));
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(true)); GUILayout.Label(this.scienceContent, GUILayout.ExpandWidth(true));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.EndVertical(); GUILayout.EndVertical();
   
GUI.DragWindow(); base.ModuleWindow(id);
} }
   
// 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;
} }
   
private void onGameStateLoad(ConfigNode node) private void onGameStateLoad(ConfigNode node)
{ {
this.initCurrencies(); this.initCurrencies();
} }
   
private void initCurrencies() private void initCurrencies()
{ {
Tools.PostDebugMessage( Tools.PostDebugMessage(
this, this,
"Initializing currencies." + "Initializing currencies." +
"\n\tFunding.Instance={0}" + "\n\tFunding.Instance={0}" +
"ResearchAndDevelopment.Instance={1}" + "ResearchAndDevelopment.Instance={1}" +
"Reputation.Instance={2}", "Reputation.Instance={2}",
Funding.Instance == null ? "NULL" : Funding.Instance.ToString(), Funding.Instance == null ? "NULL" : Funding.Instance.ToString(),
ResearchAndDevelopment.Instance == null ? "NULL" : ResearchAndDevelopment.Instance.ToString(), ResearchAndDevelopment.Instance == null ? "NULL" : ResearchAndDevelopment.Instance.ToString(),
Reputation.Instance == null ? "NULL" : Reputation.Instance.ToString() Reputation.Instance == null ? "NULL" : Reputation.Instance.ToString()
); );
   
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;
} }
   
/* /*
* 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;  
   
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);
GameEvents.onGameStateLoad.Add(this.onGameStateLoad); GameEvents.onGameStateLoad.Add(this.onGameStateLoad);
   
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 = double.NaN; this.currentFunds = double.NaN;
this.currentScience = float.NaN; this.currentScience = float.NaN;
this.currentReputation = float.NaN; this.currentReputation = float.NaN;
} }
   
~VOID_CareerStatus() public override void Dispose()
{ {
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);
GameEvents.onGameStateLoad.Remove(this.onGameStateLoad); GameEvents.onGameStateLoad.Remove(this.onGameStateLoad);
   
VOID_CareerStatus.Instance = null; base.Dispose();
  }
   
  ~VOID_CareerStatus()
  {
  this.Dispose();
} }
} }
} }
   
   
  // VOID
  //
  // VOID_ConfigModule.cs
  //
  // Copyright © 2015, toadicus
  // All rights reserved.
  //
  // Redistribution and use in source and binary forms, with or without modification,
  // are permitted provided that the following conditions are met:
  //
  // 1. Redistributions of source code must retain the above copyright notice,
  // this list of conditions and the following disclaimer.
  //
  // 2. Redistributions in binary form must reproduce the above copyright notice,
  // this list of conditions and the following disclaimer in the documentation and/or other
  // materials provided with the distribution.
  //
  // 3. Neither the name of the copyright holder nor the names of its contributors may be used
  // to endorse or promote products derived from this software without specific prior written permission.
  //
  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
  using KSP;
  using System;
  using ToadicusTools;
  using UnityEngine;
 
  namespace VOID
  {
  public class VOID_ConfigWindow : VOID_SingletonWindow<VOID_ConfigWindow>
  {
  public override bool InValidScene
  {
  get
  {
  return true;
  }
  }
 
  public override bool InValidGame
  {
  get
  {
  return true;
  }
  }
 
  public VOID_ConfigWindow() : base()
  {
  this.Name = "VOID Configuration";
  }
 
  public override void ModuleWindow(int id)
  {
  GUILayout.BeginVertical();
 
  this.core.DrawConfigurables();
 
  GUILayout.EndVertical();
 
  base.ModuleWindow(id);
  }
 
  ~VOID_ConfigWindow()
  {
  this.Dispose();
  }
  }
  }
 
// VOID // VOID
// //
// VOID_Data.cs // VOID_Data.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 KerbalEngineer.VesselSimulator; using KerbalEngineer.VesselSimulator;
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 static class VOID_Data public static class VOID_Data
{ {
private static Dictionary<int, IVOID_DataValue> dataValues = new Dictionary<int, IVOID_DataValue>(); private static Dictionary<int, IVOID_DataValue> dataValues = new Dictionary<int, IVOID_DataValue>();
   
public static Dictionary<int, IVOID_DataValue> DataValues public static Dictionary<int, IVOID_DataValue> DataValues
{ {
get get
{ {
return dataValues; return dataValues;
} }
} }
   
#region Constants #region Constants
   
private static double kerbinGee; private static double kerbinGee;
   
public static double KerbinGee public static double KerbinGee
{ {
get get
{ {
if (kerbinGee == default(double)) if (kerbinGee == default(double))
{ {
kerbinGee = Core.HomeBody.gravParameter / (Core.HomeBody.Radius * Core.HomeBody.Radius); kerbinGee = Core.HomeBody.gravParameter / (Core.HomeBody.Radius * Core.HomeBody.Radius);
} }
   
return kerbinGee; return kerbinGee;
} }
} }
   
#endregion #endregion
   
#region Core Data #region Core Data
   
public static VOIDCore Core public static VOIDCore Core
{ {
get get
{ {
if (!CoreInitialized) if (!CoreInitialized)
{ {
return null; return null;
} }
   
switch (HighLogic.LoadedScene) switch (HighLogic.LoadedScene)
{ {
case GameScenes.EDITOR: case GameScenes.EDITOR:
return (VOIDCore)VOIDCore_Editor.Instance; return (VOIDCore)VOIDCore_Editor.Instance;
case GameScenes.FLIGHT: case GameScenes.FLIGHT:
return (VOIDCore)VOIDCore_Flight.Instance; return (VOIDCore)VOIDCore_Flight.Instance;
case GameScenes.SPACECENTER: case GameScenes.SPACECENTER:
return (VOIDCore)VOIDCore_SpaceCentre.Instance; return (VOIDCore)VOIDCore_SpaceCentre.Instance;
default: default:
return null; return null;
} }
} }
} }
   
public static bool CoreInitialized public static bool CoreInitialized
{ {
get get
{ {
switch (HighLogic.LoadedScene) switch (HighLogic.LoadedScene)
{ {
case GameScenes.EDITOR: case GameScenes.EDITOR:
return VOIDCore_Editor.Initialized; return VOIDCore_Editor.Initialized;
case GameScenes.FLIGHT: case GameScenes.FLIGHT:
return VOIDCore_Flight.Initialized; return VOIDCore_Flight.Initialized;
case GameScenes.SPACECENTER: case GameScenes.SPACECENTER:
return VOIDCore_SpaceCentre.Initialized; return VOIDCore_SpaceCentre.Initialized;
default: default:
return false; return false;
} }
} }
} }
   
#endregion #endregion
   
#region Atmosphere #region Atmosphere
   
public static readonly VOID_DoubleValue atmDensity = public static readonly VOID_DoubleValue atmDensity =
new VOID_DoubleValue( new VOID_DoubleValue(
"Atmosphere Density", "Atmosphere Density",
new Func<double>(() => Core.vessel.atmDensity * 1000f), new Func<double>(() => Core.Vessel.atmDensity * 1000f),
"g/m³" "g/m³"
); );
   
public static readonly VOID_FloatValue atmLimit = public static readonly VOID_FloatValue atmLimit =
new VOID_FloatValue( new VOID_FloatValue(
"Atmosphere Limit", "Atmosphere Limit",
new Func<float>(() => Core.vessel.mainBody.maxAtmosphereAltitude), new Func<float>(() => Core.Vessel.mainBody.maxAtmosphereAltitude),
"m" "m"
); );
   
public static readonly VOID_DoubleValue atmPressure = public static readonly VOID_DoubleValue atmPressure =
new VOID_DoubleValue( new VOID_DoubleValue(
"Pressure", "Pressure",
new Func<double>(() => Core.vessel.staticPressure), new Func<double>(() => Core.Vessel.staticPressure),
"atm" "atm"
); );
   
public static readonly VOID_FloatValue temperature = public static readonly VOID_FloatValue temperature =
new VOID_FloatValue( new VOID_FloatValue(
"Temperature", "Temperature",
new Func<float>(() => Core.vessel.flightIntegrator.getExternalTemperature()), new Func<float>(() => Core.Vessel.flightIntegrator.getExternalTemperature()),
"°C" "°C"
); );
   
#endregion #endregion
   
#region Attitude #region Attitude
   
public static readonly VOID_StrValue vesselHeading = public static readonly VOID_StrValue vesselHeading =
new VOID_StrValue( new VOID_StrValue(
"Heading", "Heading",
delegate() delegate()
{ {
double heading = Core.vessel.getSurfaceHeading(); double heading = Core.Vessel.getSurfaceHeading();
string cardinal = VOID_Tools.get_heading_text(heading); string cardinal = VOID_Tools.get_heading_text(heading);
   
return string.Format( return string.Format(
"{0}° {1}", "{0}° {1}",
heading.ToString("F2"), heading.ToString("F2"),
cardinal cardinal
); );
} }
); );
   
public static readonly VOID_DoubleValue vesselPitch = public static readonly VOID_DoubleValue vesselPitch =
new VOID_DoubleValue( new VOID_DoubleValue(
"Pitch", "Pitch",
() => Core.vessel.getSurfacePitch(), () => Core.Vessel.getSurfacePitch(),
"°" "°"
); );
   
#endregion #endregion
   
#region Career #region Career
   
public static readonly VOID_StrValue fundingStatus = public static readonly VOID_StrValue fundingStatus =
new VOID_StrValue( new VOID_StrValue(
string.Intern("Funds"), string.Intern("Funds"),
delegate() delegate()
{ {
if (VOID_CareerStatus.Instance == null) if (VOID_CareerStatus.Instance == null)
{ {
return string.Empty; return string.Empty;
} }
   
return string.Format("{0} ({1})", return string.Format("{0} ({1})",
VOID_CareerStatus.Instance.currentFunds.ToString("#,#.##"), VOID_CareerStatus.Instance.currentFunds.ToString("#,#.##"),
VOID_CareerStatus.formatDelta(VOID_CareerStatus.Instance.lastFundsChange) VOID_CareerStatus.formatDelta(VOID_CareerStatus.Instance.lastFundsChange)
); );
} }
); );
   
public static readonly VOID_StrValue reputationStatus = public static readonly VOID_StrValue reputationStatus =
new VOID_StrValue( new VOID_StrValue(
string.Intern("Reputation"), string.Intern("Reputation"),
delegate() delegate()
{ {
if (VOID_CareerStatus.Instance == null) if (VOID_CareerStatus.Instance == null)
{ {
return string.Empty; return string.Empty;
} }
   
return string.Format("{0} ({1})", return string.Format("{0} ({1})",
VOID_CareerStatus.Instance.currentReputation.ToString("#,#.##"), VOID_CareerStatus.Instance.currentReputation.ToString("#,#.##"),
VOID_CareerStatus.formatDelta(VOID_CareerStatus.Instance.lastRepChange) VOID_CareerStatus.formatDelta(VOID_CareerStatus.Instance.lastRepChange)
); );
} }
); );
   
public static readonly VOID_StrValue scienceStatus = public static readonly VOID_StrValue scienceStatus =
new VOID_StrValue( new VOID_StrValue(
string.Intern("Science"), string.Intern("Science"),
delegate() delegate()
{ {
if (VOID_CareerStatus.Instance == null) if (VOID_CareerStatus.Instance == null)
{ {
return string.Empty; return string.Empty;
} }
   
return string.Format("{0} ({1})", return string.Format("{0} ({1})",
VOID_CareerStatus.Instance.currentScience.ToString("#,#.##"), VOID_CareerStatus.Instance.currentScience.ToString("#,#.##"),
VOID_CareerStatus.formatDelta(VOID_CareerStatus.Instance.lastScienceChange) VOID_CareerStatus.formatDelta(VOID_CareerStatus.Instance.lastScienceChange)
); );
} }
); );
   
#endregion #endregion
   
#region Control #region Control
   
public static readonly VOID_FloatValue mainThrottle = public static readonly VOID_FloatValue mainThrottle =
new VOID_FloatValue( new VOID_FloatValue(
"Throttle", "Throttle",
new Func<float>(() => Core.vessel.ctrlState.mainThrottle * 100f), new Func<float>(() => Core.Vessel.ctrlState.mainThrottle * 100f),
"%" "%"
); );
   
#endregion #endregion
   
#region Engineering #region Engineering
   
public static readonly VOID_IntValue partCount = public static readonly VOID_IntValue partCount =
new VOID_IntValue( new VOID_IntValue(
"Parts", "Parts",
new Func<int>(() => Core.vessel.Parts.Count), new Func<int>(() => Core.Vessel.Parts.Count),
"" ""
); );
   
#region Mass #region Mass
   
public static readonly VOID_StrValue comboResourceMass = public static readonly VOID_StrValue comboResourceMass =
new VOID_StrValue( new VOID_StrValue(
"Resource Mass (curr / total)", "Resource Mass (curr / total)",
delegate() delegate()
{ {
return string.Format("{0} / {1}", return string.Format("{0} / {1}",
stageResourceMass.ValueUnitString("F3"), stageResourceMass.ValueUnitString("F3"),
resourceMass.ValueUnitString("F3") resourceMass.ValueUnitString("F3")
); );
} }
); );
   
public static readonly VOID_DoubleValue resourceMass = public static readonly VOID_DoubleValue resourceMass =
new VOID_DoubleValue( new VOID_DoubleValue(
"Resource Mass", "Resource Mass",
delegate() delegate()
{ {
if (Core.Stages == null || Core.LastStage == null) if (Core.Stages == null || Core.LastStage == null)
{ {
return double.NaN; return double.NaN;
} }
   
  return Core.LastStage.totalResourceMass;
  },
  "tons"
  );
   
  public static readonly VOID_DoubleValue stageResourceMass =
  new VOID_DoubleValue(
  "Resource Mass (Stage)",
  delegate()
  {
  if (Core.LastStage == null)
  {
  return double.NaN;
  }
   
return Core.LastStage.resourceMass; return Core.LastStage.resourceMass;
},  
"tons"  
);  
   
public static readonly VOID_DoubleValue stageResourceMass =  
new VOID_DoubleValue(  
"Resource Mass (Stage)",  
delegate()  
{  
if (Core.LastStage == null)  
{  
return double.NaN;  
}  
   
return Core.LastStage.totalResourceMass;  
}, },
"tons" "tons"
); );
   
public static readonly VOID_DoubleValue totalMass = public static readonly VOID_DoubleValue totalMass =
new VOID_DoubleValue( new VOID_DoubleValue(
"Total Mass", "Total Mass",
delegate() delegate()
{ {
if (Core.Stages == null || Core.LastStage == null) if (Core.Stages == null || Core.LastStage == null)
{ {
return double.NaN; return double.NaN;
} }
   
return Core.LastStage.totalMass; return Core.LastStage.totalMass;
}, },
"tons" "tons"
); );
   
#endregion #endregion
   
#region DeltaV #region DeltaV
   
public static readonly VOID_DoubleValue stageDeltaV = public static readonly VOID_DoubleValue stageDeltaV =
new VOID_DoubleValue( new VOID_DoubleValue(
"DeltaV (Current Stage)", "DeltaV (Current Stage)",
delegate() delegate()
{ {
if (Core.Stages == null || Core.LastStage == null) if (Core.Stages == null || Core.LastStage == null)
return double.NaN; return double.NaN;
return Core.LastStage.deltaV; return Core.LastStage.deltaV;
}, },
"m/s" "m/s"
); );
   
public static readonly VOID_DoubleValue totalDeltaV = public static readonly VOID_DoubleValue totalDeltaV =
new VOID_DoubleValue( new VOID_DoubleValue(
"DeltaV (Total)", "DeltaV (Total)",
delegate() delegate()
{ {
if (Core.Stages == null || Core.LastStage == null) if (Core.Stages == null || Core.LastStage == null)
return double.NaN; return double.NaN;
return Core.LastStage.totalDeltaV; return Core.LastStage.totalDeltaV;
}, },
"m/s" "m/s"
); );
   
#endregion #endregion
   
#region Propulsion #region Propulsion
   
public static readonly VOID_StrValue currmaxThrustWeight = public static readonly VOID_StrValue currmaxThrustWeight =
new VOID_StrValue( new VOID_StrValue(
"T:W (curr/max)", "T:W (curr/max)",
delegate() delegate()
{ {
if (Core.Stages == null || Core.LastStage == null) if (Core.Stages == null || Core.LastStage == null)
return "N/A"; return "N/A";
   
return string.Format( return string.Format(
"{0} / {1}", "{0} / {1}",
(VOID_Data.currThrustWeight.Value).ToString("F2"), (VOID_Data.currThrustWeight.Value).ToString("F2"),
(VOID_Data.maxThrustWeight.Value).ToString("F2") (VOID_Data.maxThrustWeight.Value).ToString("F2")
); );
} }
); );
   
public static readonly VOID_StrValue currmaxThrust = public static readonly VOID_StrValue currmaxThrust =
new VOID_StrValue( new VOID_StrValue(
"Thrust (curr/max)", "Thrust (curr/max)",
delegate() delegate()
{ {
if (Core.Stages == null || Core.LastStage == null) if (Core.Stages == null || Core.LastStage == null)
return "N/A"; return "N/A";
   
double currThrust = Core.LastStage.actualThrust; double currThrust = Core.LastStage.actualThrust;
double maxThrust = Core.LastStage.thrust; double maxThrust = Core.LastStage.thrust;
   
return string.Format( return string.Format(
"{0} / {1}", "{0} / {1}",
currThrust.ToString("F1"), currThrust.ToString("F1"),
maxThrust.ToString("F1") maxThrust.ToString("F1")
); );
} }
); );
   
public static readonly VOID_DoubleValue stageMassFlow = public static readonly VOID_DoubleValue stageMassFlow =
new VOID_DoubleValue( new VOID_DoubleValue(
"Stage Mass Flow", "Stage Mass Flow",
delegate() delegate()
{ {
if (Core.LastStage == null) if (Core.LastStage == null)
{ {
return double.NaN; return double.NaN;
} }
   
double stageIsp = Core.LastStage.isp; return Core.LastStage.MassFlow();
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" "Mg/s"
); );
   
public static readonly VOID_DoubleValue stageNominalThrust = public static readonly VOID_DoubleValue stageNominalThrust =
new VOID_DoubleValue( new VOID_DoubleValue(
"Nominal Stage Thrust", "Nominal Stage Thrust",
delegate() delegate()
{ {
if (Core.LastStage == null) if (Core.LastStage == null)
{ {
return double.NaN; return double.NaN;
} }
   
if (Core.LastStage.actualThrust == 0d) return Core.LastStage.NominalThrust();
{  
return Core.LastStage.thrust;  
}  
else  
{  
return Core.LastStage.actualThrust;  
}  
}, },
"kN" "kN"
); );
   
#endregion #endregion
   
#region Kinetics #region Kinetics
   
public static readonly VOID_DoubleValue currThrustWeight = public static readonly VOID_DoubleValue currThrustWeight =
new VOID_DoubleValue( new VOID_DoubleValue(
"T:W Ratio", "T:W Ratio",
delegate() delegate()
{ {
if (Core.LastStage == null) if (Core.LastStage == null)
{ {
return double.NaN; return double.NaN;
} }
   
return Core.LastStage.actualThrustToWeight; return Core.LastStage.actualThrustToWeight;
}, },
"" ""
); );
   
   
   
public static readonly VOID_DoubleValue maxThrustWeight = public static readonly VOID_DoubleValue maxThrustWeight =
new VOID_DoubleValue( new VOID_DoubleValue(
"T:W Ratio", "T:W Ratio",
delegate() delegate()
{ {
if (Core.LastStage == null) if (Core.LastStage == null)
{ {
return double.NaN; return double.NaN;
} }
   
return Core.LastStage.thrustToWeight; return Core.LastStage.thrustToWeight;
}, },
"" ""
); );
   
public static readonly VOID_DoubleValue nominalThrustWeight = public static readonly VOID_DoubleValue nominalThrustWeight =
new VOID_DoubleValue( new VOID_DoubleValue(
"Thrust-to-Weight Ratio", "Thrust-to-Weight Ratio",
delegate() delegate()
{ {
if (HighLogic.LoadedSceneIsEditor || currThrustWeight.Value == 0d) if (HighLogic.LoadedSceneIsEditor || currThrustWeight.Value == 0d)
{ {
return maxThrustWeight.Value; return maxThrustWeight.Value;
} }
   
return currThrustWeight.Value; return currThrustWeight.Value;
}, },
"" ""
); );
   
public static readonly VOID_DoubleValue surfaceThrustWeight = public static readonly VOID_DoubleValue surfaceThrustWeight =
new VOID_DoubleValue( new VOID_DoubleValue(
"Max T:W @ surface", "Max T:W @ surface",
delegate() delegate()
{ {
if (Core.Stages == null || Core.LastStage == null) if (Core.Stages == null || Core.LastStage == null)
return double.NaN; return double.NaN;
   
double maxThrust = Core.LastStage.thrust; double maxThrust = Core.LastStage.thrust;
double mass = Core.LastStage.totalMass; double mass = Core.LastStage.totalMass;
double gravity = (VOIDCore.Constant_G * Core.vessel.mainBody.Mass) / double gravity = (VOIDCore.Constant_G * Core.Vessel.mainBody.Mass) /
(Core.vessel.mainBody.Radius * Core.vessel.mainBody.Radius); (Core.Vessel.mainBody.Radius * Core.Vessel.mainBody.Radius);
double weight = mass * gravity; double weight = mass * gravity;
   
return maxThrust / weight; return maxThrust / weight;
}, },
"" ""
); );
   
public static readonly VOID_Vector3dValue vesselThrustOffset = public static readonly VOID_Vector3dValue vesselThrustOffset =
new VOID_Vector3dValue( new VOID_Vector3dValue(
"Thrust Offset", "Thrust Offset",
delegate() delegate()
{ {
if (Core.vessel == null) if (Core.Vessel == null)
{ {
return Vector3d.zero; return Vector3d.zero;
} }
   
List<PartModule> engineModules = Core.vessel.getModulesOfType<PartModule>(); List<PartModule> engineModules = Core.Vessel.getModulesOfType<PartModule>();
   
Vector3d thrustPos = Vector3d.zero; Vector3d thrustPos = Vector3d.zero;
Vector3d thrustDir = Vector3d.zero; Vector3d thrustDir = Vector3d.zero;
float thrust = 0; float thrust = 0;
   
foreach (PartModule engine in engineModules) foreach (PartModule engine in engineModules)
{ {
float moduleThrust = 0; float moduleThrust = 0;
   
switch (engine.moduleName) switch (engine.moduleName)
{ {
case "ModuleEngines": case "ModuleEngines":
case "ModuleEnginesFX": case "ModuleEnginesFX":
break; break;
default: default:
continue; continue;
} }
   
if (!engine.isEnabled) if (!engine.isEnabled)
{ {
continue; continue;
} }
   
CenterOfThrustQuery cotQuery = new CenterOfThrustQuery(); CenterOfThrustQuery cotQuery = new CenterOfThrustQuery();
   
if (engine is ModuleEngines) if (engine is ModuleEngines)
{ {
ModuleEngines engineModule = engine as ModuleEngines; ModuleEngines engineModule = engine as ModuleEngines;
   
moduleThrust = engineModule.finalThrust; moduleThrust = engineModule.finalThrust;
   
engineModule.OnCenterOfThrustQuery(cotQuery); engineModule.OnCenterOfThrustQuery(cotQuery);
} }
else // engine is ModuleEnginesFX else // engine is ModuleEnginesFX
{ {
ModuleEnginesFX engineFXModule = engine as ModuleEnginesFX; ModuleEnginesFX engineFXModule = engine as ModuleEnginesFX;
   
moduleThrust = engineFXModule.finalThrust; moduleThrust = engineFXModule.finalThrust;
   
engineFXModule.OnCenterOfThrustQuery(cotQuery); engineFXModule.OnCenterOfThrustQuery(cotQuery);
} }
   
if (moduleThrust != 0d) if (moduleThrust != 0d)
{ {
cotQuery.thrust = moduleThrust; cotQuery.thrust = moduleThrust;
} }
   
thrustPos += cotQuery.pos * cotQuery.thrust; thrustPos += cotQuery.pos * cotQuery.thrust;
thrustDir += cotQuery.dir * cotQuery.thrust; thrustDir += cotQuery.dir * cotQuery.thrust;
thrust += cotQuery.thrust; thrust += cotQuery.thrust;
} }
   
if (thrust != 0) if (thrust != 0)
{ {
thrustPos /= thrust; thrustPos /= thrust;
thrustDir /= thrust; thrustDir /= thrust;
} }
   
Transform vesselTransform = Core.vessel.transform; Transform vesselTransform = Core.Vessel.transform;
   
thrustPos = vesselTransform.InverseTransformPoint(thrustPos); thrustPos = vesselTransform.InverseTransformPoint(thrustPos);
thrustDir = vesselTransform.InverseTransformDirection(thrustDir); thrustDir = vesselTransform.InverseTransformDirection(thrustDir);
   
Vector3d thrustOffset = VectorTools.PointDistanceToLine( Vector3d thrustOffset = VectorTools.PointDistanceToLine(
thrustPos, thrustDir.normalized, Core.vessel.findLocalCenterOfMass()); thrustPos, thrustDir.normalized, Core.Vessel.findLocalCenterOfMass());
   
Tools.PostDebugMessage(typeof(VOID_Data), "vesselThrustOffset:\n" + Tools.PostDebugMessage(typeof(VOID_Data), "vesselThrustOffset:\n" +
"\tthrustPos: {0}\n" + "\tthrustPos: {0}\n" +
"\tthrustDir: {1}\n" + "\tthrustDir: {1}\n" +
"\tthrustOffset: {2}\n" + "\tthrustOffset: {2}\n" +
"\tvessel.CoM: {3}", "\tvessel.CoM: {3}",
thrustPos, thrustPos,
thrustDir.normalized, thrustDir.normalized,
thrustOffset, thrustOffset,
Core.vessel.findWorldCenterOfMass() Core.Vessel.findWorldCenterOfMass()
); );
   
return thrustOffset; return thrustOffset;
}, },
"m" "m"
); );
   
#endregion #endregion
   
#region Air Breathing #region Air Breathing
   
public static readonly VOID_StrValue intakeAirStatus = public static readonly VOID_StrValue intakeAirStatus =
new VOID_StrValue( new VOID_StrValue(
"Intake Air (Curr / Req)", "Intake Air (Curr / Req)",
delegate() delegate()
{ {
double currentAmount; double currentAmount;
double currentRequirement; double currentRequirement;
   
currentAmount = 0d; currentAmount = 0d;
currentRequirement = 0d; currentRequirement = 0d;
   
foreach (Part part in Core.vessel.Parts) foreach (Part part in Core.Vessel.Parts)
{ {
if (part.enabled) if (part.enabled)
{ {
ModuleEngines engineModule; ModuleEngines engineModule;
ModuleEnginesFX enginesFXModule; ModuleEnginesFX enginesFXModule;
List<Propellant> propellantList = null; List<Propellant> propellantList = null;
   
if (part.tryGetFirstModuleOfType<ModuleEngines>(out engineModule)) if (part.tryGetFirstModuleOfType<ModuleEngines>(out engineModule))
{ {
propellantList = engineModule.propellants; propellantList = engineModule.propellants;
} }
else if (part.tryGetFirstModuleOfType<ModuleEnginesFX>(out enginesFXModule)) else if (part.tryGetFirstModuleOfType<ModuleEnginesFX>(out enginesFXModule))
{ {
propellantList = enginesFXModule.propellants; propellantList = enginesFXModule.propellants;
} }
   
if (propellantList != null) if (propellantList != null)
{ {
foreach (Propellant propellant in propellantList) foreach (Propellant propellant in propellantList)
{ {
if (propellant.name == "IntakeAir") if (propellant.name == "IntakeAir")
{ {
currentRequirement += propellant.currentRequirement / TimeWarp.fixedDeltaTime; currentRequirement += propellant.currentRequirement / TimeWarp.fixedDeltaTime;
break; break;
} }
} }
} }
} }
   
ModuleResourceIntake intakeModule; ModuleResourceIntake intakeModule;
   
if (part.enabled && part.tryGetFirstModuleOfType<ModuleResourceIntake>(out intakeModule)) if (part.enabled && part.tryGetFirstModuleOfType<ModuleResourceIntake>(out intakeModule))
{ {
if (intakeModule.resourceName == "IntakeAir") if (intakeModule.resourceName == "IntakeAir")
{ {
currentAmount += intakeModule.airFlow; currentAmount += intakeModule.airFlow;
} }
} }
} }
   
if (currentAmount == 0 && currentRequirement == 0) if (currentAmount == 0 && currentRequirement == 0)
{ {
return "N/A"; return "N/A";
} }
   
return string.Format("{0:F3} / {1:F3}", currentAmount, currentRequirement); return string.Format("{0:F3} / {1:F3}", currentAmount, currentRequirement);
} }
); );
   
#endregion #endregion
   
#region Crew #region Crew
   
public static readonly VOID_IntValue vesselCrewCount = public static readonly VOID_IntValue vesselCrewCount =
new VOID_IntValue( new VOID_IntValue(
"Crew Onboard", "Crew Onboard",
delegate() delegate()
{ {
if (Core.vessel != null) if (Core.Vessel != null)
{ {
return Core.vessel.GetCrewCount(); return Core.Vessel.GetCrewCount();
} }
else else
{ {
return 0; return 0;
} }
}, },
"" ""
); );
   
public static readonly VOID_IntValue vesselCrewCapacity = public static readonly VOID_IntValue vesselCrewCapacity =
new VOID_IntValue( new VOID_IntValue(
"Crew Capacity", "Crew Capacity",
delegate() delegate()
{ {
if (Core.vessel != null) if (Core.Vessel != null)
{ {
return Core.vessel.GetCrewCapacity(); return Core.Vessel.GetCrewCapacity();
} }
else else
{ {
return 0; return 0;
} }
}, },
"" ""
); );
   
#endregion #endregion
   
#endregion #endregion
   
#region Location #region Location
   
public const double kscLongitude = 285.442323427289 * Math.PI / 180d; public const double kscLongitude = 285.442323427289 * Math.PI / 180d;
public const double kscLatitude = -0.0972112860655246 * Math.PI / 180d; public const double kscLatitude = -0.0972112860655246 * Math.PI / 180d;
   
public static readonly VOID_DoubleValue downrangeDistance = public static readonly VOID_DoubleValue downrangeDistance =
new VOID_DoubleValue( new VOID_DoubleValue(
"Downrange Distance", "Downrange Distance",
delegate() delegate()
{ {
   
if (Core.vessel == null || if (Core.Vessel == null ||
Planetarium.fetch == null || Planetarium.fetch == null ||
Core.vessel.mainBody != Planetarium.fetch.Home) Core.Vessel.mainBody != Planetarium.fetch.Home)
{ {
return double.NaN; return double.NaN;
} }
   
double vesselLongitude = Core.vessel.longitude * Math.PI / 180d; double vesselLongitude = Core.Vessel.longitude * Math.PI / 180d;
double vesselLatitude = Core.vessel.latitude * Math.PI / 180d; double vesselLatitude = Core.Vessel.latitude * Math.PI / 180d;
   
double diffLon = vesselLongitude - kscLongitude; double diffLon = Math.Abs(vesselLongitude - kscLongitude);
double diffLat = vesselLatitude - kscLatitude;  
  double cosVesselLatitude = Math.Cos(vesselLatitude);
double sinHalfDiffLat = Math.Sin(diffLat / 2d); double sinDiffLon = Math.Sin(diffLon);
double sinHalfDiffLon = Math.Sin(diffLon / 2d);  
  double term1 = cosVesselLatitude * sinDiffLon;
double cosVesselLon = Math.Cos(vesselLongitude);  
double cosKSCLon = Math.Cos(kscLongitude); double cosKSCLatitude = Math.Cos(kscLatitude);
  double sinVesselLatitude = Math.Sin(vesselLatitude);
double haversine = double sinKSCLatitude = Math.Sin(kscLatitude);
sinHalfDiffLat * sinHalfDiffLat + double cosDiffLon = Math.Cos(diffLon);
cosVesselLon * cosKSCLon * sinHalfDiffLon * sinHalfDiffLon;  
  double term2 = cosKSCLatitude * sinVesselLatitude - sinKSCLatitude * cosVesselLatitude * cosDiffLon;
double arc = 2d * Math.Atan2(Math.Sqrt(haversine), Math.Sqrt(1d - haversine));  
  double term3 = sinKSCLatitude * sinVesselLatitude + cosKSCLatitude * cosVesselLatitude * cosDiffLon;
return Core.vessel.mainBody.Radius * arc;  
  double arc = Math.Atan2(Math.Sqrt(term1 * term1 + term2 * term2), term3);
   
  return arc * Core.Vessel.mainBody.Radius;
}, },
"m" "m"
); );
   
public static readonly VOID_StrValue surfLatitude = public static readonly VOID_StrValue surfLatitude =
new VOID_StrValue( new VOID_StrValue(
"Latitude", "Latitude",
new Func<string>(() => VOID_Tools.GetLatitudeString(Core.vessel)) new Func<string>(() => VOID_Tools.GetLatitudeString(Core.Vessel))
); );
   
public static readonly VOID_StrValue surfLongitude = public static readonly VOID_StrValue surfLongitude =
new VOID_StrValue( new VOID_StrValue(
"Longitude", "Longitude",
new Func<string>(() => VOID_Tools.GetLongitudeString(Core.vessel)) new Func<string>(() => VOID_Tools.GetLongitudeString(Core.Vessel))
); );
   
public static readonly VOID_DoubleValue trueAltitude = public static readonly VOID_DoubleValue trueAltitude =
new VOID_DoubleValue( new VOID_DoubleValue(
"Altitude (true)", "Altitude (true)",
delegate() delegate()
{ {
double alt_true = Core.vessel.orbit.altitude - Core.vessel.terrainAltitude; 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, // HACK: This assumes that on worlds with oceans, all water is fixed at 0 m,
// and water covers the whole surface at 0 m. // and water covers the whole surface at 0 m.
if (Core.vessel.terrainAltitude < 0 && Core.vessel.mainBody.ocean) if (Core.Vessel.terrainAltitude < 0 && Core.Vessel.mainBody.ocean)
alt_true = Core.vessel.orbit.altitude; alt_true = Core.Vessel.orbit.altitude;
return alt_true; return alt_true;
}, },
"m" "m"
); );
   
#endregion #endregion
   
#region Kinematics #region Kinematics
   
public static readonly VOID_DoubleValue geeForce = public static readonly VOID_DoubleValue geeForce =
new VOID_DoubleValue( new VOID_DoubleValue(
"G-force", "G-force",
new Func<double>(() => Core.vessel.geeForce), new Func<double>(() => Core.Vessel.geeForce),
"gees" "gees"
); );
   
public static readonly VOID_DoubleValue horzVelocity = public static readonly VOID_DoubleValue horzVelocity =
new VOID_DoubleValue( new VOID_DoubleValue(
"Horizontal speed", "Horizontal speed",
new Func<double>(() => Core.vessel.horizontalSrfSpeed), new Func<double>(() => Core.Vessel.horizontalSrfSpeed),
"m/s" "m/s"
); );
   
public static readonly VOID_DoubleValue surfVelocity = public static readonly VOID_DoubleValue surfVelocity =
new VOID_DoubleValue( new VOID_DoubleValue(
"Surface velocity", "Surface velocity",
new Func<double>(() => Core.vessel.srf_velocity.magnitude), new Func<double>(() => Core.Vessel.srf_velocity.magnitude),
"m/s" "m/s"
); );
   
public static readonly VOID_DoubleValue vertVelocity = public static readonly VOID_DoubleValue vertVelocity =
new VOID_DoubleValue( new VOID_DoubleValue(
"Vertical speed", "Vertical speed",
new Func<double>(() => Core.vessel.verticalSpeed), new Func<double>(() => Core.Vessel.verticalSpeed),
"m/s" "m/s"
); );
   
public static readonly VOID_DoubleValue vesselAccel = public static readonly VOID_DoubleValue vesselAccel =
new VOID_DoubleValue( new VOID_DoubleValue(
"Acceleration", "Acceleration",
() => geeForce * KerbinGee, () => geeForce * KerbinGee,
"m/s²" "m/s²"
); );
   
public static readonly VOID_DoubleValue vesselAngularVelocity = public static readonly VOID_DoubleValue vesselAngularVelocity =
new VOID_DoubleValue( new VOID_DoubleValue(
"Angular Velocity", "Angular Velocity",
delegate() delegate()
{ {
if (Core.vessel != null) if (Core.Vessel != null)
{ {
return Core.vessel.angularVelocity.magnitude; return Core.Vessel.angularVelocity.magnitude;
} }
else else
{ {
return double.NaN; return double.NaN;
} }
}, },
"rad/s" "rad/s"
); );
   
#endregion #endregion
   
#region Navigation #region Navigation
   
public static int upcomingManeuverNodes public static int upcomingManeuverNodes
{ {
get get
{ {
if (Core.vessel == null || if (Core.Vessel == null ||
Core.vessel.patchedConicSolver == null || Core.Vessel.patchedConicSolver == null ||
Core.vessel.patchedConicSolver.maneuverNodes == null) Core.Vessel.patchedConicSolver.maneuverNodes == null)
{ {
return 0; return 0;
} }
   
return Core.vessel.patchedConicSolver.maneuverNodes.Count; return Core.Vessel.patchedConicSolver.maneuverNodes.Count;
} }
} }
   
public static readonly VOID_StrValue burnTimeDoneAtNode = public static readonly VOID_StrValue burnTimeDoneAtNode =
new VOID_StrValue( new VOID_StrValue(
"Full burn time to be half done at node", "Full burn time to be half done at node",
delegate() delegate()
{ {
if (Core.LastStage == null && upcomingManeuverNodes < 1) if (Core.LastStage == null && upcomingManeuverNodes < 1)
{ {
return "N/A"; return "N/A";
} }
   
ManeuverNode node = Core.vessel.patchedConicSolver.maneuverNodes[0]; ManeuverNode node = Core.Vessel.patchedConicSolver.maneuverNodes[0];
   
if ((node.UT - Planetarium.GetUniversalTime()) < 0) if ((node.UT - Planetarium.GetUniversalTime()) < 0)
{ {
return string.Empty; return string.Empty;
} }
   
double interval = (node.UT - currentNodeBurnDuration) - Planetarium.GetUniversalTime(); double interval = (node.UT - currentNodeBurnDuration) - Planetarium.GetUniversalTime();
   
if (double.IsNaN(interval)) if (double.IsNaN(interval))
{ {
return string.Intern("NaN"); return string.Intern("NaN");
} }
   
int sign = Math.Sign(interval); int sign = Math.Sign(interval);
interval = Math.Abs(interval); interval = Math.Abs(interval);
   
string format; string format;
   
if (sign >= 0) if (sign >= 0)
{ {
format = string.Intern("T - {0}"); format = string.Intern("T - {0}");
} }
else else
{ {
format = string.Intern("T + {0}"); format = string.Intern("T + {0}");
} }
   
return string.Format(format, VOID_Tools.FormatInterval(interval)); return string.Format(format, VOID_Tools.FormatInterval(interval));
} }
); );
   
public static readonly VOID_StrValue burnTimeHalfDoneAtNode = public static readonly VOID_StrValue burnTimeHalfDoneAtNode =
new VOID_StrValue( new VOID_StrValue(
"Full burn time to be half done at node", "Full burn time to be half done at node",
delegate() delegate()
{ {
if (Core.LastStage == null && upcomingManeuverNodes < 1) if (Core.LastStage == null && upcomingManeuverNodes < 1)
{ {
return "N/A"; return "N/A";
} }
   
ManeuverNode node = Core.vessel.patchedConicSolver.maneuverNodes[0]; ManeuverNode node = Core.Vessel.patchedConicSolver.maneuverNodes[0];
   
if ((node.UT - Planetarium.GetUniversalTime()) < 0) if ((node.UT - Planetarium.GetUniversalTime()) < 0)
{ {
return string.Empty; return string.Empty;
} }
   
double interval = (node.UT - currentNodeHalfBurnDuration) - Planetarium.GetUniversalTime(); double interval = (node.UT - currentNodeHalfBurnDuration) - Planetarium.GetUniversalTime();
   
if (double.IsNaN(interval)) if (double.IsNaN(interval))
{ {
return string.Intern("NaN"); return string.Intern("NaN");
} }
   
int sign = Math.Sign(interval); int sign = Math.Sign(interval);
interval = Math.Abs(interval); interval = Math.Abs(interval);
   
string format; string format;
   
if (sign >= 0) if (sign >= 0)
{ {
format = string.Intern("T - {0}"); format = string.Intern("T - {0}");
} }
else else
{ {
format = string.Intern("T + {0}"); format = string.Intern("T + {0}");
} }
   
return string.Format(format, VOID_Tools.FormatInterval(interval)); return string.Format(format, VOID_Tools.FormatInterval(interval));
} }
); );
   
public static readonly VOID_DoubleValue currManeuverDeltaV = public static readonly VOID_DoubleValue currManeuverDeltaV =
new VOID_DoubleValue( new VOID_DoubleValue(
"Current Maneuver Delta-V", "Current Maneuver Delta-V",
delegate() delegate()
{ {
if (upcomingManeuverNodes > 0) if (upcomingManeuverNodes > 0)
{ {
return Core.vessel.patchedConicSolver.maneuverNodes[0].DeltaV.magnitude; return Core.Vessel.patchedConicSolver.maneuverNodes[0].DeltaV.magnitude;
} }
else else
{ {
return double.NaN; return double.NaN;
} }
}, },
"m/s" "m/s"
); );
   
public static readonly VOID_DoubleValue currManeuverDVRemaining = public static readonly VOID_DoubleValue currManeuverDVRemaining =
new VOID_DoubleValue( new VOID_DoubleValue(
"Remaining Maneuver Delta-V", "Remaining Maneuver Delta-V",
delegate() delegate()
{ {
if (upcomingManeuverNodes > 0) if (upcomingManeuverNodes > 0)
{ {
return Core.vessel.patchedConicSolver.maneuverNodes[0].GetBurnVector(Core.vessel.orbit).magnitude; return Core.Vessel.patchedConicSolver.maneuverNodes[0].GetBurnVector(Core.Vessel.orbit).magnitude;
} }
else else
{ {
return double.NaN; return double.NaN;
} }
}, },
"m/s" "m/s"
); );
   
public static readonly VOID_DoubleValue currentNodeBurnDuration = public static readonly VOID_DoubleValue currentNodeBurnDuration =
new VOID_DoubleValue( new VOID_DoubleValue(
"Total Burn Time", "Total Burn Time",
delegate() delegate()
{ {
if (Core.LastStage == null || currManeuverDeltaV.Value == double.NaN) if (currManeuverDeltaV.Value == double.NaN)
{ {
return double.NaN; return double.NaN;
} }
   
double stageThrust = stageNominalThrust; return realVesselBurnTime(currManeuverDeltaV.Value);
   
return burnTime(currManeuverDeltaV.Value, totalMass, stageMassFlow, stageThrust);  
}, },
"s" "s"
); );
   
public static readonly VOID_DoubleValue currentNodeBurnRemaining = public static readonly VOID_DoubleValue currentNodeBurnRemaining =
new VOID_DoubleValue( new VOID_DoubleValue(
"Burn Time Remaining", "Burn Time Remaining",
delegate() delegate()
{ {
if (Core.LastStage == null || currManeuverDVRemaining == double.NaN) if (currManeuverDVRemaining.Value == double.NaN)
{ {
return double.NaN; return double.NaN;
} }
   
double stageThrust = stageNominalThrust; return realVesselBurnTime(currManeuverDVRemaining.Value);
   
return burnTime(currManeuverDVRemaining, totalMass, stageMassFlow, stageThrust);  
}, },
"s" "s"
); );
   
public static readonly VOID_DoubleValue currentNodeHalfBurnDuration = public static readonly VOID_DoubleValue currentNodeHalfBurnDuration =
new VOID_DoubleValue( new VOID_DoubleValue(
"Half Burn Time", "Half Burn Time",
delegate() delegate()
{ {
if (Core.LastStage == null || currManeuverDeltaV.Value == double.NaN) if (currManeuverDeltaV.Value == double.NaN)
{ {
return double.NaN; return double.NaN;
} }
   
double stageThrust = stageNominalThrust; return realVesselBurnTime(currManeuverDeltaV.Value / 2d);
   
return burnTime(currManeuverDeltaV.Value / 2d, totalMass, stageMassFlow, stageThrust);  
}, },
"s" "s"
); );
   
public static readonly VOID_DoubleValue nextManeuverDeltaV = public static readonly VOID_DoubleValue nextManeuverDeltaV =
new VOID_DoubleValue( new VOID_DoubleValue(
"Current Maneuver Delta-V", "Current Maneuver Delta-V",
delegate() delegate()
{ {
if (upcomingManeuverNodes > 1) if (upcomingManeuverNodes > 1)
{ {
return Core.vessel.patchedConicSolver.maneuverNodes[1].DeltaV.magnitude; return Core.Vessel.patchedConicSolver.maneuverNodes[1].DeltaV.magnitude;
} }
else else
{ {
return double.NaN; return double.NaN;
} }
}, },
"m/s" "m/s"
); );
   
#endregion #endregion
   
#region Orbits #region Orbits
   
public static readonly VOID_StrValue primaryName = public static readonly VOID_StrValue primaryName =
new VOID_StrValue( new VOID_StrValue(
VOID_Localization.void_primary, VOID_Localization.void_primary,
delegate() delegate()
{ {
if (Core.vessel == null) if (Core.Vessel == null)
{ {
return string.Empty; return string.Empty;
} }
return Core.vessel.mainBody.name; return Core.Vessel.mainBody.name;
} }
); );
   
public static readonly VOID_DoubleValue orbitAltitude = public static readonly VOID_DoubleValue orbitAltitude =
new VOID_DoubleValue( new VOID_DoubleValue(
"Altitude (ASL)", "Altitude (ASL)",
new Func<double>(() => Core.vessel.orbit.altitude), new Func<double>(() => Core.Vessel.orbit.altitude),
"m" "m"
); );
   
public static readonly VOID_DoubleValue orbitVelocity = public static readonly VOID_DoubleValue orbitVelocity =
new VOID_DoubleValue( new VOID_DoubleValue(
VOID_Localization.void_velocity, VOID_Localization.void_velocity,
new Func<double>(() => Core.vessel.orbit.vel.magnitude), new Func<double>(() => Core.Vessel.orbit.vel.magnitude),
"m/s" "m/s"
); );
   
public static readonly VOID_DoubleValue orbitApoAlt = public static readonly VOID_DoubleValue orbitApoAlt =
new VOID_DoubleValue( new VOID_DoubleValue(
VOID_Localization.void_apoapsis, VOID_Localization.void_apoapsis,
new Func<double>(() => Core.vessel.orbit.ApA), new Func<double>(() => Core.Vessel.orbit.ApA),
"m" "m"
); );
   
public static readonly VOID_DoubleValu