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.

* text=auto * text=auto
* eol=lf * eol=lf
   
  # These files are text and should be normalized (convert crlf => lf)
  *.cs text diff=csharp
  *.cfg text
  *.csproj text
  *.sln text
   
  # Images should be treated as binary
  # (binary is a macro for -text -diff)
  *.png binary
   
  // VOID
  //
  // AVOID_SaveValue.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
  {
  [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
  public class AVOID_SaveValue : Attribute
  {
  public string Name
  {
  get;
  private set;
  }
 
  public AVOID_SaveValue(string fieldName)
  {
  this.Name = fieldName;
  }
  }
  }
 
 
  // VOID
  //
  // VOID_ScenesAttribute.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
  {
  [AttributeUsage(AttributeTargets.Class)]
  public class VOID_ScenesAttribute : Attribute
  {
  public GameScenes[] ValidScenes
  {
  get;
  private set;
  }
 
  public VOID_ScenesAttribute(params GameScenes[] validScenes)
  {
  this.ValidScenes = validScenes;
  }
  }
  }
 
 
  // VOID
  //
  // VOID_ScenesAttribute.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
  {
  [AttributeUsage(AttributeTargets.Class)]
  public class VOID_GameModesAttribute : Attribute
  {
  public Game.Modes[] ValidModes
  {
  get;
  private set;
  }
 
  public VOID_GameModesAttribute(params Game.Modes[] validModes)
  {
  this.ValidModes = validModes;
  }
  }
  }
 
 
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
  //
  // IVOID_DataValue.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 interface IVOID_DataValue
  {
  string Label { get; }
  string Units { get; }
  object Value { get; }
 
  void Refresh();
  string ValueUnitString();
  void DoGUIHorizontal();
  }
  }
 
 
  // VOID
  //
  // IVOID_Module.cs
  //
  // Copyright © 2014, toadicus
  // All rights reserved.
  //
  // Redistribution and use in source and binary forms, with or without modification,
  // are permitted provided that the following conditions are met:
  //
  // 1. Redistributions of source code must retain the above copyright notice,
  // this list of conditions and the following disclaimer.
  //
  // 2. Redistributions in binary form must reproduce the above copyright notice,
  // this list of conditions and the following disclaimer in the documentation and/or other
  // materials provided with the distribution.
  //
  // 3. Neither the name of the copyright holder nor the names of its contributors may be used
  // to endorse or promote products derived from this software without specific prior written permission.
  //
  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
  using System;
 
  namespace VOID
  {
  public interface IVOID_Module
  {
  string Name { get; }
  bool Active { get; set; }
  bool GUIRunning { get; }
  bool InValidScene { get; }
  bool InValidGame { get; }
 
  void DrawGUI();
  void StartGUI();
  void StopGUI();
 
  void DrawConfigurables();
 
  void LoadConfig();
 
  void Save(KSP.IO.PluginConfiguration config);
  }
 
  public interface IVOID_BehaviorModule : IVOID_Module
  {
  void Update();
  void FixedUpdate();
  void OnDestroy();
  }
  }
 
  // VOID
  //
  // IVOID_SaveValue.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 interface IVOID_SaveValue
  {
  Type type { get; }
  object value { get; }
  void SetValue(object v);
  }
  }
 
 
file:b/API/VOIDCore.cs (new)
  // VOID
  //
  // IVOID_Core.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 KerbalEngineer.VesselSimulator;
  using KSP;
  using System;
  using System.Collections.Generic;
  using ToadicusTools;
  using UnityEngine;
 
  namespace VOID
  {
  public abstract class VOIDCore : VOID_WindowModule, IVOID_Module
  {
  public const double Constant_G = 6.674e-11;
  public const int CONFIG_VERSION = 2;
 
  public abstract int ConfigVersion { get; }
  public virtual bool configNeedsUpdate { get; set; }
 
  public abstract int WindowID { get; }
  public abstract bool configDirty { get; set; }
  public abstract bool powerAvailable { get; protected set; }
 
  public abstract IList<IVOID_Module> Modules { get; }
 
  public abstract float UpdateTimer { get; protected set; }
  public abstract double UpdatePeriod { get; }
 
  public virtual float saveTimer { get; protected set; }
 
  public abstract GUISkin Skin { get; }
 
  public abstract CelestialBody HomeBody { get; }
  public abstract IList<CelestialBody> AllBodies { get; }
  public abstract List<CelestialBody> SortedBodyList { get; protected set; }
 
  public abstract VesselType[] AllVesselTypes { get; protected set; }
  public abstract Stage LastStage { 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 onSkinChanged;
 
  public virtual void OnGUI() {}
 
  public override void LoadConfig()
  {
  base.LoadConfig();
  }
 
  public abstract void SaveConfig();
 
  public override void Save(KSP.IO.PluginConfiguration config)
  {
  base.Save(config);
  }
  }
 
  public delegate void VOIDEventHandler(object sender);
  }
 
 
file:b/API/VOIDMaster.cs (new)
  // VOID
  //
  // VOIDMaster.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.
  //
  ///////////////////////////////////////////////////////////////////////////////
  //
  // Much, much credit to Younata, Adammada, Nivvydaskrl and to all the authors
  // behind MechJeb, RemoteTech Relay Network, ISA MapSat, and Protractor for some
  // invaluable functions and making your nicely written code available to learn from.
  //
  ///////////////////////////////////////////////////////////////////////////////
  //
  // This software uses VesselSimulator and Engineer.Extensions from Engineer Redux.
  // Engineer Redux (c) 2013 cybutek
  // Used by permission.
  //
  ///////////////////////////////////////////////////////////////////////////////
 
  using System;
  using UnityEngine;
  using KerbalEngineer.VesselSimulator;
  using ToadicusTools;
 
  namespace VOID
  {
  public abstract class VOIDMaster<T> : MonoBehaviour
  where T : VOIDCore_Generic<T>, new()
  {
  protected T Core;
 
  public abstract void Awake();
 
  public virtual void Update()
  {
  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.Core.SaveConfig ();
  this.Core.Dispose();
  this.Core = null;
  return;
  }
 
  if (this.Core == null && this.InValidScene())
  {
  this.LogDebug("We have no Core and the scene is valid for this master; re-trying Awake.");
  this.Awake();
  return;
  }
 
  this.Core.Update ();
 
  if (this.Core.FactoryReset)
  {
  this.LogDebug("Factory reset is true; deleting config and disposing!");
 
  KSP.IO.File.Delete<T>("config.xml");
  this.Core.Dispose();
  this.Core = null;
  }
  }
 
  public virtual void FixedUpdate()
  {
  if (this.Core == null)
  {
  return;
  }
 
  this.Core.FixedUpdate ();
  }
 
  public virtual void OnGUI()
  {
  if (this.Core == null)
  {
  return;
  }
 
  this.Core.OnGUI();
  }
 
  public virtual void OnDestroy()
  {
  if (this.Core == null)
  {
  return;
  }
 
  this.Core.OnDestroy();
  }
 
  public virtual void OnApplicationQuit()
  {
  if (this.Core == null)
  {
  return;
  }
 
  this.Core.OnApplicationQuit();
  }
 
  protected virtual bool InValidScene()
  {
  foreach (var attr in this.GetType().GetCustomAttributes(true))
  {
  if (attr is KSPAddon)
  {
  KSPAddon addonAttr = (KSPAddon)attr;
 
  switch (addonAttr.startup)
  {
  case KSPAddon.Startup.EveryScene:
  return true;
  case KSPAddon.Startup.EditorAny:
  return HighLogic.LoadedSceneIsEditor;
  case KSPAddon.Startup.Flight:
  return HighLogic.LoadedSceneIsFlight;
  case KSPAddon.Startup.MainMenu:
  return HighLogic.LoadedScene == GameScenes.MAINMENU;
  case KSPAddon.Startup.SpaceCentre:
  return HighLogic.LoadedScene == GameScenes.SPACECENTER;
  case KSPAddon.Startup.TrackingStation:
  return HighLogic.LoadedScene == GameScenes.TRACKSTATION;
  default:
  return false;
  }
  }
  }
 
  return false;
  }
  }
  }
 
  // VOID
  //
  // VOID_HUDModule.cs
  //
  // Copyright © 2014, toadicus
  // All rights reserved.
  //
  // Redistribution and use in source and binary forms, with or without modification,
  // are permitted provided that the following conditions are met:
  //
  // 1. Redistributions of source code must retain the above copyright notice,
  // this list of conditions and the following disclaimer.
  //
  // 2. Redistributions in binary form must reproduce the above copyright notice,
  // this list of conditions and the following disclaimer in the documentation and/or other
  // materials provided with the distribution.
  //
  // 3. Neither the name of the copyright holder nor the names of its contributors may be used
  // to endorse or promote products derived from this software without specific prior written permission.
  //
  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
  using KerbalEngineer.VesselSimulator;
  using KSP;
  using System;
  using System.Collections.Generic;
  using System.Text;
  using ToadicusTools;
  using UnityEngine;
 
  namespace VOID
  {
  public abstract class VOID_HUDModule : VOID_Module
  {
  [AVOID_SaveValue("colorIndex")]
  protected VOID_SaveValue<int> _colorIndex;
 
  protected List<Color> textColors;
 
  [AVOID_SaveValue("positionsLocked")]
  protected VOID_SaveValue<bool> positionsLocked;
 
  public virtual int ColorIndex
  {
  get
  {
  return this._colorIndex;
  }
  set
  {
  if (this._colorIndex >= this.textColors.Count - 1)
  {
  this._colorIndex.value = 0;
  return;
  }
 
  this._colorIndex.value = value;
  }
  }
 
  public virtual List<HUDWindow> Windows
  {
  get;
  protected set;
  }
 
  public VOID_HUDModule() : base()
  {
  this._colorIndex = (VOID_SaveValue<int>)0;
 
  this.textColors = new List<Color>();
 
  this.textColors.Add(Color.green);
  this.textColors.Add(Color.black);
  this.textColors.Add(Color.white);
  this.textColors.Add(Color.red);
  this.textColors.Add(Color.blue);
  this.textColors.Add(Color.yellow);
  this.textColors.Add(Color.gray);
  this.textColors.Add(Color.cyan);
  this.textColors.Add(Color.magenta);
 
  this.positionsLocked = (VOID_SaveValue<bool>)true;
 
  this.Windows = new List<HUDWindow>();
  }
 
  public override void DrawGUI()
  {
  VOID_Styles.labelHud.normal.textColor = textColors [ColorIndex];
 
  GUI.skin = this.core.Skin;
 
  if (HighLogic.LoadedSceneIsEditor ||
  (TimeWarp.WarpMode == TimeWarp.Modes.LOW) || (TimeWarp.CurrentRate <= TimeWarp.MaxPhysicsRate)
  )
  {
  SimManager.RequestSimulation();
  }
 
  foreach (HUDWindow window in this.Windows)
  {
  window.WindowPos = GUILayout.Window(
  this.core.WindowID,
  window.WindowPos,
  VOID_Tools.GetWindowHandler(window.WindowFunction),
  GUIContent.none,
  GUIStyle.none
  );
  }
  }
 
  public override void DrawConfigurables()
  {
  base.DrawConfigurables();
 
  if (GUILayout.Button (string.Intern("Change HUD color"), GUILayout.ExpandWidth (false)))
  {
  ++this.ColorIndex;
  }
 
  if (GUILayout.Button(string.Intern("Reset HUD Positions"), GUILayout.ExpandWidth(false)))
  {
  foreach (HUDWindow window in this.Windows)
  {
  window.WindowPos = new Rect(window.defaultWindowPos);
  }
  }
 
  this.positionsLocked.value = GUITools.Toggle(this.positionsLocked, "Lock HUD Positions");
  }
 
  public override void LoadConfig()
  {
  base.LoadConfig();
 
  var config = KSP.IO.PluginConfiguration.CreateForType<VOID_HUDModule>();
  config.load();
 
  foreach (HUDWindow window in this.Windows)
  {
  string saveName = string.Format("{0}_{1}", this.GetType().Name, window.WindowName);
  Rect loadedPos = config.GetValue(saveName, window.defaultWindowPos);
 
  window.WindowPos = loadedPos;
  }
  }
 
  public override void Save(KSP.IO.PluginConfiguration config)
  {
  base.Save(config);
 
  foreach (HUDWindow window in this.Windows)
  {
  string saveName = string.Format("{0}_{1}", this.GetType().Name, window.WindowName);
  config.SetValue(saveName, window.WindowPos);
  }
  }
  }
 
  public class HUDWindow
  {
  public readonly Rect defaultWindowPos;
 
  private Rect _windowPos;
 
  public Action<int> WindowFunction
  {
  get;
  private set;
  }
 
  public Rect WindowPos
  {
  get
  {
  return this._windowPos;
  }
  set
  {
  if (value != this._windowPos)
  {
  this._windowPos = value;
 
  if (VOID_Data.Core != null)
  {
  VOID_Data.Core.configDirty = true;
  }
  }
  }
  }
 
  public string WindowName
  {
  get;
  private set;
  }
 
  private HUDWindow() {}
 
  public HUDWindow(string name, Action<int> windowFunc, Rect defaultPos)
  {
  this.WindowName = name;
  this.WindowFunction = windowFunc;
  this.defaultWindowPos = defaultPos;
  this.WindowPos = new Rect(this.defaultWindowPos);
  }
  }
  }
 
 
  // VOID
  //
  // VOID_Module.cs
  //
  // Copyright © 2014, toadicus
  // All rights reserved.
  //
  // Redistribution and use in source and binary forms, with or without modification,
  // are permitted provided that the following conditions are met:
  //
  // 1. Redistributions of source code must retain the above copyright notice,
  // this list of conditions and the following disclaimer.
  //
  // 2. Redistributions in binary form must reproduce the above copyright notice,
  // this list of conditions and the following disclaimer in the documentation and/or other
  // materials provided with the distribution.
  //
  // 3. Neither the name of the copyright holder nor the names of its contributors may be used
  // to endorse or promote products derived from this software without specific prior written permission.
  //
  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Reflection;
  using ToadicusTools;
  using UnityEngine;
 
  namespace VOID
  {
  public abstract class VOID_Module : IVOID_Module
  {
  /*
  * Fields
  * */
  [AVOID_SaveValue("Active")]
  protected VOID_SaveValue<bool> active = (VOID_SaveValue<bool>)false;
 
  protected float lastUpdate = 0;
 
  private GameScenes[] validScenes;
  private Game.Modes[] validModes;
 
  /*
  * Properties
  * */
 
  public virtual bool Active
  {
  get
  {
  return this.active && this.InValidGame && this.InValidScene;
  }
  set
  {
  this.active.value = value && this.InValidGame && this.InValidScene;
  }
  }
 
  public virtual bool GUIRunning
  {
  get
  {
  if (
  RenderingManager.fetch == null ||
  RenderingManager.fetch.postDrawQueue == null ||
  RenderingManager.fetch.postDrawQueue.Length < 4
  )
  {
  return false;
  }
  else
  {
  Delegate callback = RenderingManager.fetch.postDrawQueue[3];
  if (callback == null)
  {
  return false;
  }
 
  return callback.GetInvocationList().Contains((Callback)this.DrawGUI);
  }
  }
  }
 
  public virtual bool InValidGame
  {
  get
  {
  return this.ValidModes.Contains(HighLogic.CurrentGame.Mode);
  }
  }
 
  public virtual bool InValidScene
  {
  get
  {
  return this.ValidScenes.Contains(HighLogic.LoadedScene);
  }
  }
 
  public virtual string Name
  {
  get;
  protected set;
  }
 
  public virtual Game.Modes[] ValidModes
  {
  get
  {
  if (this.validModes == null)
  {
  Tools.PostDebugMessage(this, "validModes is null when checking inValidGame; fetching attribute.");
  foreach (var attr in this.GetType().GetCustomAttributes(false))
  {
  if (attr is VOID_GameModesAttribute)
  {
  VOID_GameModesAttribute addonAttr = (VOID_GameModesAttribute)attr;
 
  this.validModes = addonAttr.ValidModes;
 
  Tools.PostDebugMessage("Found VOID_GameModesAttribute; validScenes set.");
 
  break;
  }
  }
 
  if (this.validModes == null)
  {
  this.validModes = new Game.Modes[]
  {
  Game.Modes.CAREER,
  Game.Modes.SANDBOX,
  Game.Modes.SCENARIO,
  Game.Modes.SCENARIO_NON_RESUMABLE,
  Game.Modes.SCIENCE_SANDBOX
  };
 
  Tools.PostDebugMessage("No VOID_GameModesAttribute found; validScenes defaulted to flight.");
  }
  }
 
  return this.validModes;
  }
  }
 
  public virtual GameScenes[] ValidScenes
  {
  get
  {
  if (this.validScenes == null)
  {
  Tools.PostDebugMessage(this, "validScenes is null when checking inValidScene; fetching attribute.");
  foreach (var attr in this.GetType().GetCustomAttributes(false))
  {
  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 Vessel Vessel
  {
  get
  {
  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
  * */
  public virtual void StartGUI()
  {
  if (!this.Active || this.GUIRunning)
  {
  return;
  }
 
  Tools.PostDebugMessage (string.Format("Adding {0} to the draw queue.", this.GetType().Name));
  RenderingManager.AddToPostDrawQueue (3, this.DrawGUI);
  }
 
  public virtual void StopGUI()
  {
  if (!this.GUIRunning)
  {
  return;
  }
  Tools.PostDebugMessage (string.Format("Removing {0} from the draw queue.", this.GetType().Name));
  RenderingManager.RemoveFromPostDrawQueue (3, this.DrawGUI);
  }
 
  public abstract void DrawGUI();
 
  public virtual void DrawConfigurables() {}
 
  public virtual void LoadConfig()
  {
  var config = KSP.IO.PluginConfiguration.CreateForType<VOID_Module> ();
  config.load ();
 
  if (this is VOIDCore)
  {
  int configVersion = config.GetValue("VOID_Core_configValue", 2);
 
  if (configVersion < VOIDCore.CONFIG_VERSION)
  {
  ((VOIDCore)this).configNeedsUpdate = true;
  }
  }
 
  foreach (var field in this.GetType().GetMembers(
  BindingFlags.NonPublic |
  BindingFlags.Public |
  BindingFlags.Instance |
  BindingFlags.FlattenHierarchy
  ))
  {
  if (!(field is FieldInfo || field is PropertyInfo))
  {
  continue;
  }
 
  if (field is PropertyInfo && (field as PropertyInfo).GetIndexParameters().Length > 0)
  {
  continue;
  }
 
  object[] attrs = field.GetCustomAttributes(typeof(AVOID_SaveValue), false);
 
  if (attrs.Length == 0) {
  continue;
  }
 
  AVOID_SaveValue attr = attrs.FirstOrDefault () as AVOID_SaveValue;
 
  string fieldName = string.Empty;
 
  if (this is VOIDCore || this.core.configNeedsUpdate)
  {
  string typeName = this.GetType().Name;;
 
  if (this is VOIDCore && ((VOIDCore)this).configNeedsUpdate)
  {
  if (this is VOIDCore_Flight)
  {
  typeName = "VOID_Core";
  }
  else if (this is VOIDCore_Editor)
  {
  typeName = "VOID_EditorCore";
  }
  }
 
  fieldName = string.Format("{0}_{1}", typeName, attr.Name);
  }
  else
  {
  fieldName = string.Format(
  "{0}_{1}_{2}",
  this.GetType().Name,
  Enum.GetName(typeof(GameScenes), HighLogic.LoadedScene),
  attr.Name
  );
  }
 
  Tools.PostDebugMessage(string.Format("{0}: Loading field {1}.", this.GetType().Name, fieldName));
 
  object fieldValue;
 
  if (field is FieldInfo)
  {
  fieldValue = (field as FieldInfo).GetValue(this);
  }
  else
  {
  fieldValue = (field as PropertyInfo).GetValue(this, null);
  }
 
  bool convertBack = false;
  if (fieldValue is IVOID_SaveValue)
  {
  fieldValue = (fieldValue as IVOID_SaveValue).value;
  convertBack = true;
  }
 
  fieldValue = config.GetValue(fieldName, fieldValue);
 
  if (convertBack)
  {
  Type type = typeof(VOID_SaveValue<>).MakeGenericType (fieldValue.GetType ());
  IVOID_SaveValue convertValue = Activator.CreateInstance (type) as IVOID_SaveValue;
  convertValue.SetValue (fieldValue);
  fieldValue = convertValue;
  }
 
  if (field is FieldInfo)
  {
  (field as FieldInfo).SetValue(this, fieldValue);
  }
  else
  {
  (field as PropertyInfo).SetValue(this, fieldValue, null);
  }
 
  Tools.PostDebugMessage(string.Format("{0}: Loaded field {1}.", this.GetType().Name, fieldName));
  }
  }
 
  public virtual void Save(KSP.IO.PluginConfiguration config)
  {
  foreach (var field in this.GetType().GetMembers(
  BindingFlags.Instance |
  BindingFlags.NonPublic |
  BindingFlags.Public |
  BindingFlags.FlattenHierarchy
  ))
  {
  object[] attrs = field.GetCustomAttributes(typeof(AVOID_SaveValue), false);
 
  if (attrs.Length == 0) {
  continue;
  }
 
  AVOID_SaveValue attr = attrs.FirstOrDefault () as AVOID_SaveValue;
 
  string fieldName;
 
  if (this is VOIDCore)
  {
  fieldName = string.Format("{0}_{1}", this.GetType().Name, attr.Name);
  }
  else
  {
  fieldName = string.Format(
  "{0}_{1}_{2}",
  this.GetType().Name,
  Enum.GetName(typeof(GameScenes), HighLogic.LoadedScene),
  attr.Name
  );
  }
 
  object fieldValue;
 
  if (field is FieldInfo)
  {
  fieldValue = (field as FieldInfo).GetValue(this);
  }
  else
  {
  fieldValue = (field as PropertyInfo).GetValue(this, null);
  }
 
  if (fieldValue is IVOID_SaveValue)
  {
  fieldValue = (fieldValue as IVOID_SaveValue).value;
  }
 
  config.SetValue(fieldName, fieldValue);
 
  Tools.PostDebugMessage(string.Format("{0}: Saved field {1}.", this.GetType().Name, fieldName));
  }
  }
  }
 
  public abstract class VOID_WindowModule : VOID_Module
  {
  [AVOID_SaveValue("WindowPos")]
  protected Rect WindowPos;
  protected float defWidth;
  protected float defHeight;
 
  protected bool decorateWindow;
 
  protected string inputLockName;
 
  public VOID_WindowModule() : base()
  {
  this.defWidth = 250f;
  this.defHeight = 50f;
 
  this.decorateWindow = true;
 
  this.inputLockName = string.Concat(this.Name, "_edlock");
 
  this.WindowPos = new Rect(Screen.width / 2, Screen.height / 2, this.defWidth, this.defHeight);
  }
 
  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()
  {
  GUI.skin = this.core.Skin;
 
  Rect _Pos = this.WindowPos;
 
  _Pos = GUILayout.Window(
  this.core.WindowID,
  _Pos,
  VOID_Tools.GetWindowHandler(this.ModuleWindow),
  this.Name,
  GUILayout.Width(this.defWidth),
  GUILayout.Height(this.defHeight)
  );
 
  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)
  {
  case GameScenes.EDITOR:
  InputLockManager.SetControlLock(
  ControlTypes.EDITOR_ICON_HOVER | ControlTypes.EDITOR_ICON_PICK |
  ControlTypes.EDITOR_PAD_PICK_COPY | ControlTypes.EDITOR_PAD_PICK_COPY,
  this.inputLockName
  );
  EditorLogic.fetch.Lock(false, false, false, this.inputLockName);
  break;
  case GameScenes.FLIGHT:
  InputLockManager.SetControlLock(ControlTypes.CAMERACONTROLS, this.inputLockName);
  break;
  case GameScenes.SPACECENTER:
  InputLockManager.SetControlLock(
  ControlTypes.KSC_FACILITIES | ControlTypes.CAMERACONTROLS,
  this.inputLockName
  );
  break;
  }
  }
 
  protected void removeUILock()
  {
  switch (HighLogic.LoadedScene)
  {
  case GameScenes.EDITOR:
  EditorLogic.fetch.Unlock(this.inputLockName);
  break;
  case GameScenes.FLIGHT:
  InputLockManager.RemoveControlLock(this.inputLockName);
  break;
  case GameScenes.SPACECENTER:
  InputLockManager.RemoveControlLock(this.inputLockName);
  break;
  }
  }
  }
  }
 
 
  // 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_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
  }
  }
 
 
  ACTIVE_TEXTURE_MANAGER_CONFIG
  {
  folder = VOID
  enabled = true
  OVERRIDES
  {
  VOID/Textures/.*
  {
  compress = false
  mipmaps = false
  scale = 1
  max_size = 0
  }
  }
  }
 
 Binary files /dev/null and b/GameData/VOID/Textures/fundsgreen.png differ
 Binary files /dev/null and b/GameData/VOID/Textures/fundsred.png differ
 Binary files /dev/null and b/GameData/VOID/Textures/repgreen.png differ
 Binary files /dev/null and b/GameData/VOID/Textures/repred.png differ
 Binary files /dev/null and b/GameData/VOID/Textures/science.png differ
 Binary files /dev/null and b/GameData/VOID/Textures/void_appIcon_dark.png differ
 Binary files /dev/null and b/GameData/VOID/Textures/void_appIcon_dark_glow.png differ
 Binary files /dev/null and b/GameData/VOID/Textures/void_appIcon_light.png differ
 Binary files /dev/null and b/GameData/VOID/Textures/void_appIcon_light_glow.png differ
 Binary files /dev/null and b/GameData/VOID/Textures/void_icon_dark.png differ
 Binary files /dev/null and b/GameData/VOID/Textures/void_icon_dark_glow.png differ
 Binary files /dev/null and b/GameData/VOID/Textures/void_icon_light.png differ
 Binary files /dev/null and b/GameData/VOID/Textures/void_icon_light_glow.png differ
file:a/IVOID_Module.cs (deleted)
// VOID  
//  
// IVOID_Module.cs  
//  
// Copyright © 2014, toadicus  
// All rights reserved.  
//  
// Redistribution and use in source and binary forms, with or without modification,  
// are permitted provided that the following conditions are met:  
//  
// 1. Redistributions of source code must retain the above copyright notice,  
// this list of conditions and the following disclaimer.  
//  
// 2. Redistributions in binary form must reproduce the above copyright notice,  
// this list of conditions and the following disclaimer in the documentation and/or other  
// materials provided with the distribution.  
//  
// 3. Neither the name of the copyright holder nor the names of its contributors may be used  
// to endorse or promote products derived from this software without specific prior written permission.  
//  
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,  
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE  
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,  
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR  
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE  
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
 
using System;  
 
namespace VOID  
{  
public interface IVOID_Module  
{  
string Name { get; }  
bool toggleActive { get; set; }  
bool guiRunning { get; }  
 
void DrawGUI();  
void StartGUI();  
void StopGUI();  
 
void DrawConfigurables();  
 
void LoadConfig();  
 
void _SaveToConfig(KSP.IO.PluginConfiguration config);  
}  
 
public interface IVOID_BehaviorModule : IVOID_Module  
{  
void Update();  
void FixedUpdate();  
}  
 
public interface IVOID_EditorModule : IVOID_Module {}  
}  
 
// 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.12.0.*")] [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_DataValue.cs
  //
  // Copyright © 2014, toadicus
  // All rights reserved.
  //
  // Redistribution and use in source and binary forms, with or without modification,
  // are permitted provided that the following conditions are met:
  //
  // 1. Redistributions of source code must retain the above copyright notice,
  // this list of conditions and the following disclaimer.
  //
  // 2. Redistributions in binary form must reproduce the above copyright notice,
  // this list of conditions and the following disclaimer in the documentation and/or other
  // materials provided with the distribution.
  //
  // 3. Neither the name of the copyright holder nor the names of its contributors may be used
  // to endorse or promote products derived from this software without specific prior written permission.
  //
  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
  using System;
  using ToadicusTools;
  using UnityEngine;
 
  namespace VOID
  {
  public class VOID_DataValue<T> : IVOID_DataValue
  {
  /*
  * Static Members
  * */
  public static implicit operator T(VOID_DataValue<T> v)
  {
  return (T)v.Value;
  }
 
  /*
  * Instance Members
  * */
  /*
  * Fields
  * */
  protected T cache;
  protected Func<T> ValueFunc;
  protected float lastUpdate;
 
  /*
  * Properties
  * */
  public string Label { get; protected set; }
  public string Units { get; protected set; }
 
  object IVOID_DataValue.Value
  {
  get
  {
  return this.Value;
  }
  }
 
  public T Value
  {
  get
  {
  if (
  (VOID_Data.Core.UpdateTimer - this.lastUpdate > VOID_Data.Core.UpdatePeriod) ||
  (this.lastUpdate > VOID_Data.Core.UpdateTimer)
  )
  {
  this.Refresh();
  }
  return (T)this.cache;
  }
  }
 
  /*
  * Methods
  * */
  public VOID_DataValue(string Label, Func<T> ValueFunc, string Units = "")
  {
  this.Label = Label;
  this.Units = Units;
  this.ValueFunc = ValueFunc;
  this.lastUpdate = 0;
 
  VOID_Data.DataValues[this.GetHashCode()] = this;
  }
 
  public void Refresh()
  {
  this.cache = this.ValueFunc.Invoke ();
  this.lastUpdate = VOID_Data.Core.UpdateTimer;
  }
 
  public T GetFreshValue()
  {
  this.Refresh ();
  return (T)this.cache;
  }
 
  public virtual string ValueUnitString() {
  return this.Value.ToString() + this.Units;
  }
 
  public virtual void DoGUIHorizontal()
  {
  GUILayout.BeginHorizontal (GUILayout.ExpandWidth (true));
  GUILayout.Label (this.Label + ":");
  GUILayout.FlexibleSpace ();
  GUILayout.Label (this.ValueUnitString(), GUILayout.ExpandWidth (false));
  GUILayout.EndHorizontal ();
  }
 
  public override int GetHashCode()
  {
  int hash;
  unchecked
  {
  hash = 79999;
 
  hash = hash * 104399 + this.Label.GetHashCode();
  hash = hash * 104399 + this.ValueFunc.GetHashCode();
  hash = hash * 104399 + this.Units.GetHashCode();
  }
 
  return hash;
  }
 
  public override string ToString()
  {
  return string.Format (
  "{0}: {1}{2}",
  this.Label,
  this.Value.ToString (),
  this.Units
  );
  }
  }
 
  public abstract class VOID_NumValue<T> : VOID_DataValue<T>, IFormattable
  where T : IFormattable, IConvertible, IComparable
  {
  public static IFormatProvider formatProvider = Tools.SIFormatter;
 
  public static implicit operator Double(VOID_NumValue<T> v)
  {
  return v.ToDouble();
  }
 
  public static implicit operator Int32(VOID_NumValue<T> v)
  {
  return v.ToInt32();
  }
 
  public static implicit operator Single(VOID_NumValue<T> v)
  {
  return v.ToSingle();
  }
 
  public VOID_NumValue(string Label, Func<T> ValueFunc, string Units = "") : base(Label, ValueFunc, Units)
  {
 
  }
 
  public virtual double ToDouble(IFormatProvider provider)
  {
  return this.Value.ToDouble(provider);
  }
 
  public virtual double ToDouble()
  {
  return this.ToDouble(formatProvider);
  }
 
  public virtual int ToInt32(IFormatProvider provider)
  {
  return this.Value.ToInt32(provider);
  }
 
  public virtual int ToInt32()
  {
  return this.ToInt32(formatProvider);
  }
 
  public virtual float ToSingle(IFormatProvider provider)
  {
  return this.Value.ToSingle(provider);
  }
 
  public virtual float ToSingle()
  {
  return this.ToSingle(formatProvider);
  }
 
  public virtual string ToString(string format)
  {
  return this.ToString(format, formatProvider);
  }
 
  public virtual string ToString(string format, IFormatProvider provider)
  {
  return string.Format (
  "{0}{1}",
  this.Value.ToString(format, provider),
  this.Units
  );
  }
 
  public virtual string ToSIString(int digits = 3, int MinMagnitude = 0, int MaxMagnitude = int.MaxValue)
  {
  return string.Format (
  "{0}{1}",
  Tools.MuMech_ToSI (this, digits, MinMagnitude, MaxMagnitude),
  this.Units
  );
  }
 
  public virtual string ValueUnitString(string format)
  {
  return this.Value.ToString(format, formatProvider) + this.Units;
  }
 
  public virtual string ValueUnitString(int digits) {
  return string.Format("{0}{1}", SIFormatProvider.ToSI(this, digits), Units);
  }
 
  public virtual string ValueUnitString(int digits, int MinMagnitude, int MaxMagnitude)
  {
  return Tools.MuMech_ToSI(this, digits, MinMagnitude, MaxMagnitude) + this.Units;
  }
 
  public virtual void DoGUIHorizontal(string format)
  {
  GUILayout.BeginHorizontal (GUILayout.ExpandWidth (true));
  GUILayout.Label (this.Label + ":");
  GUILayout.FlexibleSpace ();
  GUILayout.Label (this.ValueUnitString(format), GUILayout.ExpandWidth (false));
  GUILayout.EndHorizontal ();
  }
 
  public virtual int DoGUIHorizontal(int digits, bool precisionButton = true)
  {
  if (precisionButton)
  {
  return this.DoGUIHorizontalPrec(digits);
  }
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label(this.Label + ":", GUILayout.ExpandWidth(true));
  GUILayout.FlexibleSpace();
  GUILayout.Label(this.ValueUnitString(digits), GUILayout.ExpandWidth(false));
  GUILayout.EndHorizontal();
 
  return digits;
  }
 
  public virtual int DoGUIHorizontalPrec(int digits)
  {
  if (digits < 0 || digits > 8)
  {
  digits = 5;
  }
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label(this.Label + "ⁱ:", GUILayout.ExpandWidth(true));
  GUILayout.FlexibleSpace();
 
  GUILayout.Label(this.ValueUnitString(digits), GUILayout.ExpandWidth(false));
 
  GUILayout.EndHorizontal();
 
  if (Event.current.type == EventType.mouseUp)
  {
  Rect lastRect = GUILayoutUtility.GetLastRect();
  if (lastRect.Contains(Event.current.mousePosition))
  {
  Tools.PostDebugMessage(string.Format("{0}: Changing digits from {1}",
  this.GetType().Name,
  digits
  ));
 
  if (Event.current.button == 0)
  {
  digits = (digits + 3) % 9;
  }
  else if (Event.current.button == 1)
  {
  digits = (digits - 3) % 9;
  }
 
  if (digits < 0)
  {
  digits += 9;
  }
 
  Tools.PostDebugMessage(string.Format("{0}: Changed digits to {1}.",
  this.GetType().Name,
  digits
  ));
  }
  }
 
  return digits;
  }
  }
 
  public class VOID_DoubleValue : VOID_NumValue<double>
  {
  public VOID_DoubleValue(string Label, Func<double> ValueFunc, string Units) : base(Label, ValueFunc, Units) {}
  }
 
  public class VOID_FloatValue : VOID_NumValue<float>
  {
  public VOID_FloatValue(string Label, Func<float> ValueFunc, string Units) : base(Label, ValueFunc, Units) {}
  }
 
  public class VOID_IntValue : VOID_NumValue<int>
  {
  public VOID_IntValue(string Label, Func<int> ValueFunc, string Units) : base(Label, ValueFunc, Units) {}
  }
 
  public class VOID_StrValue : VOID_DataValue<string>
  {
  public VOID_StrValue(string Label, Func<string> ValueFunc) : base(Label, ValueFunc, "") {}
  }
 
  public class VOID_Vector3dValue : VOID_DataValue<Vector3d>
  {
  public VOID_Vector3dValue(string Label, Func<Vector3d> ValueFunc, string Units)
  : base(Label, ValueFunc, Units)
  {}
 
  public string ToString(string format)
  {
  return string.Format("{0}: {1}{2}",
  this.Label,
  this.Value.ToString(format),
  this.Units
  );
  }
 
  public string ValueUnitString(string format) {
  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_SaveValue.cs
  //
  // Copyright © 2014, toadicus
  // All rights reserved.
  //
  // Redistribution and use in source and binary forms, with or without modification,
  // are permitted provided that the following conditions are met:
  //
  // 1. Redistributions of source code must retain the above copyright notice,
  // this list of conditions and the following disclaimer.
  //
  // 2. Redistributions in binary form must reproduce the above copyright notice,
  // this list of conditions and the following disclaimer in the documentation and/or other
  // materials provided with the distribution.
  //
  // 3. Neither the name of the copyright holder nor the names of its contributors may be used
  // to endorse or promote products derived from this software without specific prior written permission.
  //
  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
  using KSP;
  using System;
  using System.Collections.Generic;
  using ToadicusTools;
  using UnityEngine;
 
  namespace VOID
  {
  public struct VOID_SaveValue<T> : IVOID_SaveValue
  {
  private T _value;
  private Type _type;
 
  private VOIDCore Core
  {
  get
  {
  return VOID_Data.Core;
  }
  }
 
  object IVOID_SaveValue.value
  {
  get
  {
  return this.value;
  }
  }
 
  public T value
  {
  get
  {
  return this._value;
  }
  set
  {
  if (this.Core != null && !System.Object.Equals(this._value, value))
  {
  Tools.PostDebugMessage (string.Format (
  "VOID: Dirtying config for type {0}." +
  "\n\t Old Value: {2}, New Value: {3}" +
  "\n\t Object.Equals(New, Old): {4}\n" +
  "{1}",
  this._type,
  new System.Diagnostics.StackTrace().ToString(),
  this._value,
  value,
  System.Object.Equals(this._value, value)
  ));
  this.Core.configDirty = true;
  }
  this._value = value;
  }
  }
 
  public Type type
  {
  get
  {
  if (this._type == null && this._value != null)
  {
  this._type = this._value.GetType ();
  }
  return this._type;
  }
  set
  {
  this._type = value;
  }
  }
 
  public void SetValue(object v)
  {
  this.value = (T)v;
  }
 
  public static implicit operator T(VOID_SaveValue<T> v)
  {
  return (T)v.value;
  }
 
  public static explicit operator VOID_SaveValue<T>(T v)
  {
  VOID_SaveValue<T> r = new VOID_SaveValue<T>();
  r.type = v.GetType();
  r.value = v;
 
  return r;
  }
 
  public override string 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_Tools.cs
  //
  // Copyright © 2014, toadicus
  // All rights reserved.
  //
  // Redistribution and use in source and binary forms, with or without modification,
  // are permitted provided that the following conditions are met:
  //
  // 1. Redistributions of source code must retain the above copyright notice,
  // this list of conditions and the following disclaimer.
  //
  // 2. Redistributions in binary form must reproduce the above copyright notice,
  // this list of conditions and the following disclaimer in the documentation and/or other
  // materials provided with the distribution.
  //
  // 3. Neither the name of the copyright holder nor the names of its contributors may be used
  // to endorse or promote products derived from this software without specific prior written permission.
  //
  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
  using KSP;
  using System;
  using System.Collections.Generic;
  using ToadicusTools;
  using UnityEngine;
 
  namespace VOID
  {
  public static class VOID_Tools
  {
  #region CelestialBody Utilities
  public static bool hasAncestor(this CelestialBody bodyA, CelestialBody bodyB)
  {
  if (bodyA == null || bodyB == null)
  {
  return false;
  }
 
  while (bodyA.orbitDriver != null)
  {
  if (bodyA.orbit.referenceBody == bodyB)
  {
  return true;
  }
 
  bodyA = bodyA.orbit.referenceBody;
  }
 
  return false;
  }
 
  public static bool NearestRelatedParents(ref CelestialBody bodyA, ref CelestialBody bodyB)
  {
  if (bodyA == null || bodyB == null || bodyA.orbitDriver == null || bodyB.orbitDriver == null)
  {
  throw new ArgumentException(string.Concat(
  "CelestialBody::FindRelatedParents: ",
  "Neither body may be null, and both bodies must have orbits."
  ));
  }
 
  CelestialBody a, b;
 
  a = bodyA;
 
  while (bodyA.orbitDriver != null)
  {
  b = bodyB;
 
  while (b.orbitDriver != null)
  {
  if (a.orbit.referenceBody == b.orbit.referenceBody)
  {
  bodyA = a;
  bodyB = b;
  return true;
  }
 
  b = b.orbit.referenceBody;
  }
 
  a = a.orbit.referenceBody;
  }
 
  return false;
  }
  #endregion
 
  #region VESSEL_EXTENSIONS_SCIENCE
  public static CBAttributeMapSO.MapAttribute GetBiome(this Vessel vessel)
  {
  CBAttributeMapSO.MapAttribute mapAttribute;
 
  try
  {
  CBAttributeMapSO BiomeMap = vessel.mainBody.BiomeMap;
 
  double lat = vessel.latitude * Math.PI / 180d;
  double lon = vessel.longitude * Math.PI / 180d;
 
  mapAttribute = BiomeMap.GetAtt(lat, lon);
 
  /*
  lon -= Math.PI / 2d;
 
  if (lon < 0d)
  {
  lon += 2d * Math.PI;
  }
 
  float v = (float)(lat / Math.PI) + 0.5f;
  float u = (float)(lon / (2d * Math.PI));
 
  Color pixelBilinear = BiomeMap.Map.GetPixelBilinear(u, v);
  mapAttribute = BiomeMap.defaultAttribute;
 
  if (BiomeMap.Map != null)
  {
  if (BiomeMap.exactSearch)
  {
  for (int i = 0; i < BiomeMap.Attributes.Length; ++i)
  {
  if (pixelBilinear == BiomeMap.Attributes[i].mapColor)
  {
  mapAttribute = BiomeMap.Attributes[i];
  }
  }
  }
  else
  {
  float zero = 0;
  float num = 1 / zero;
  for (int j = 0; j < BiomeMap.Attributes.Length; ++j)
  {
  Color mapColor = BiomeMap.Attributes[j].mapColor;
  float sqrMagnitude = ((Vector4)(mapColor - pixelBilinear)).sqrMagnitude;
  if (sqrMagnitude < num)
  {
  bool testCase = true;
  if (BiomeMap.nonExactThreshold != -1)
  {
  testCase = (sqrMagnitude < BiomeMap.nonExactThreshold);
  }
  if (testCase)
  {
  mapAttribute = BiomeMap.Attributes[j];
  num = sqrMagnitude;
  }
  }
  }
  }
  }
  */
  }
  catch (NullReferenceException)
  {
  mapAttribute = new CBAttributeMapSO.MapAttribute();
  mapAttribute.name = "N/A";
  }
 
  return mapAttribute;
  }
 
  public static ExperimentSituations GetExperimentSituation(this Vessel vessel)
  {
  if (vessel == null)
  {
  return ExperimentSituations.SrfSplashed;
  }
 
  Vessel.Situations situation = vessel.situation;
 
  switch (situation)
  {
  case Vessel.Situations.PRELAUNCH:
  case Vessel.Situations.LANDED:
  return ExperimentSituations.SrfLanded;
  case Vessel.Situations.SPLASHED:
  return ExperimentSituations.SrfSplashed;
  case Vessel.Situations.FLYING:
  if (vessel.altitude < (double)vessel.mainBody.scienceValues.flyingAltitudeThreshold)
  {
  return ExperimentSituations.FlyingLow;
  }
  else
  {
  return ExperimentSituations.FlyingHigh;
  }
  }
 
  if (vessel.altitude < (double)vessel.mainBody.scienceValues.spaceAltitudeThreshold)
  {
  return ExperimentSituations.InSpaceLow;
  }
  else
  {
  return ExperimentSituations.InSpaceHigh;
  }
  }
 
  public static string HumanString(this ExperimentSituations situation)
  {
  switch (situation)
  {
  case ExperimentSituations.FlyingHigh:
  return "Upper Atmosphere";
  case ExperimentSituations.FlyingLow:
  return "Flying";
  case ExperimentSituations.SrfLanded:
  return "Surface";
  case ExperimentSituations.InSpaceLow:
  return "Near in Space";
  case ExperimentSituations.InSpaceHigh:
  return "High in Space";
  case ExperimentSituations.SrfSplashed:
  return "Splashed Down";
  default:
  return "Unknown";
  }
  }
  #endregion
 
  #region VESSEL_EXTENSIONS_LAT_LONG
  public static string GetLongitudeString(this Vessel vessel, string format = "F4")
  {
  string dir_long = "W";
  double v_long = vessel.longitude;
 
  v_long = FixDegreeDomain(v_long);
 
  if (v_long < -180d)
  {
  v_long += 360d;
  }
  if (v_long >= 180)
  {
  v_long -= 360d;
  }
 
  if (v_long > 0)
  dir_long = "E";
 
  return string.Format("{0}° {1}", Math.Abs(v_long).ToString(format), dir_long);
  }
 
  public static string GetLatitudeString(this Vessel vessel, string format = "F4")
  {
  string dir_lat = "S";
  double v_lat = vessel.latitude;
  if (v_lat > 0)
  dir_lat = "N";
 
  return string.Format("{0}° {1}", Math.Abs(v_lat).ToString(format), dir_lat);
  }
  #endregion
 
  #region VESSEL_EXTENSIONS_GENERAL
  public static double TrueAltitude(Vessel vessel)
  {
  double trueAltitude = vessel.orbit.altitude - vessel.terrainAltitude;
 
  // HACK: This assumes that on worlds with oceans, all water is fixed at 0 m,
  // and water covers the whole surface at 0 m.
  if (vessel.terrainAltitude < 0 && vessel.mainBody.ocean)
  {
  trueAltitude = vessel.orbit.altitude;
  }
 
  return trueAltitude;
  }
 
  public static double Radius(this Vessel vessel)
  {
  double radius;
 
  radius = vessel.altitude;
 
  if (vessel.mainBody != null)
  {
  radius += vessel.mainBody.Radius;
  }
 
  return radius;
  }
  #endregion
 
  #region GEOMETRY_UTILS
  public static double FixAngleDomain(double Angle, bool Degrees = false)
  {
  double Extent = 2d * Math.PI;
  if (Degrees)
  {
  Extent = 360d;
  }
 
  Angle = Angle % (Extent);
  if (Angle < 0d)
  {
  Angle += Extent;
  }
 
  return Angle;
  }
 
  public static double FixDegreeDomain(double Angle)
  {
  return FixAngleDomain(Angle, true);
  }
  #endregion
 
  #region WINDOW_UTILS
  private static Dictionary<int, GUI.WindowFunction> functionCache;
  public static UnityEngine.GUI.WindowFunction GetWindowHandler(Action<int> func)
  {
  if (functionCache == null)
  {
  functionCache = new Dictionary<int, GUI.WindowFunction>();
  }
 
  int hashCode = func.GetHashCode();
 
  if (!functionCache.ContainsKey(hashCode))
  {
  functionCache[hashCode] = delegate (int id)
  {
  try
  {
  func(id);
  }
  #if DEBUG
  catch (ArgumentException)
  #else
  catch (ArgumentException)
  #endif
  {
  Debug.LogWarning(
  string.Format("[{0}]: ArgumentException caught during window call. This is not a bug.",
  func.Target.GetType().Name
  ));
 
  /*#if DEBUG
  Debug.LogException(ex);
  #endif*/
  }
  catch (Exception ex)
  {
  Debug.LogError(
  string.Format("[{0}]: {1} caught during window call.\nMessage:\n{2}\nStackTrace:\n{3}",
  func.Target.GetType().Name,
  ex.GetType().Name,
  ex.Message,
  ex.StackTrace
  ));
  }
  };
  }
 
  return functionCache[hashCode];
  }
 
  public static void UncacheWindow(Action<int> func)
  {
  if (functionCache != null)
  {
  int hashCode = func.GetHashCode();
 
  if (functionCache.ContainsKey(hashCode))
  {
  functionCache.Remove(hashCode);
  }
  }
  }
  #endregion
 
  #region TIME_UTILS
  /// <summary>
  /// Formats the interval given in seconds as a human-friendly
  /// time period in [[[[years, ]days, ]hours, ]minutes, and ]seconds.
  ///
  /// Uses sidereal days, since "6 hours per day" is the Kerbal standard.
  /// </summary>
  /// <returns>Human readable interval</returns>
  /// <param name="seconds"></param>
  public static string FormatInterval(double seconds)
  {
  return UnpackedTime.FromSeconds(seconds).FormatAsSpan();
  }
 
  /// <summary>
  /// Formats the date given in seconds since epoch as a human-friendly
  /// date in the format YY, DD, HH:MM:SS
  /// </summary>
  /// <returns>The date.</returns>
  /// <param name="seconds">Seconds.</param>
  public static string FormatDate(double seconds)
  {
  return UnpackedTime.FromSeconds(seconds).FormatAsDate();
  }
 
  public class UnpackedTime
  {
  public const double SecondsPerMinute = 60d;
  public const double SecondsPerHour = 3600d;
 
  public static double SecondsPerDay
  {
  get
  {
  VOID_TimeScale flags = VOID_Data.Core.TimeScale &
  (VOID_TimeScale.KERBIN_TIME | VOID_TimeScale.SOLAR_DAY | VOID_TimeScale.ROUNDED_SCALE);
 
  switch (flags)
  {
  // 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;
  }
  }
  }
 
  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)
  {
  // 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
  case VOID_TimeScale.KERBIN_TIME | VOID_TimeScale.SOLAR_DAY | VOID_TimeScale.ROUNDED_SCALE:
  case VOID_TimeScale.KERBIN_TIME | VOID_TimeScale.ROUNDED_SCALE:
  return 60 * 60 * 6 * 426;
  // Earth year, solar time
  case VOID_TimeScale.SOLAR_DAY:
  return 31556925.2507328;
  // Earth year, sidereal time
  case 0:
  return 31558149.7635456d;
  // Kerbin year, solar & sidereal time
  default:
  return 9203544.61750141d;
  }
  }
  }
 
  public static UnpackedTime FromSeconds(double seconds)
  {
  UnpackedTime time = new UnpackedTime();
 
  time.years = (int)(seconds / SecondsPerYear);
 
  seconds %= SecondsPerYear;
 
  time.days = (int)(seconds / SecondsPerDay);
 
  seconds %= SecondsPerDay;
 
  time.hours = (int)(seconds / SecondsPerHour);
 
  seconds %= SecondsPerHour;
 
  time.minutes = (int)(seconds / SecondsPerMinute);
 
  seconds %= SecondsPerMinute;
 
  time.seconds = seconds;
 
  return time;
  }
 
  public static explicit operator UnpackedTime(double seconds)
  {
  return FromSeconds(seconds);
  }
 
  public static implicit operator double(UnpackedTime time)
  {
  return time.ToSeconds();
  }
 
  public static UnpackedTime operator+ (UnpackedTime lhs, UnpackedTime rhs)
  {
  return FromSeconds(lhs.ToSeconds() + rhs.ToSeconds());
  }
 
  public static UnpackedTime operator- (UnpackedTime lhs, UnpackedTime rhs)
  {
  return FromSeconds(lhs.ToSeconds() - rhs.ToSeconds());
  }
 
  public int years;
  public int days;
  public int hours;
  public int minutes;
  public double seconds;
 
  public double ToSeconds()
  {
  return (double)years * SecondsPerYear +
  (double)days * SecondsPerDay +
  (double)hours * SecondsPerHour +
  (double)minutes * SecondsPerMinute +
  seconds;
  }
 
  public string FormatAsSpan()
  {
  string format_1 = "{0:D1}y {1:D1}d {2:D2}h {3:D2}m {4:00.0}s";
  string format_2 = "{0:D1}d {1:D2}h {2:D2}m {3:00.0}s";
  string format_3 = "{0:D2}h {1:D2}m {2:00.0}s";
  string format_4 = "{0:D2}m {1:00.0}s";
  string format_5 = "{0:00.0}s";
 
  if (this.years > 0)
  {
  return string.Format(format_1, this.years, this.days, this.hours, this.minutes, this.seconds);
  }
  else if (this.days > 0)
  {
  return string.Format(format_2, this.days, this.hours, this.minutes, this.seconds);
  }
  else if (this.hours > 0)
  {
  return string.Format(format_3, this.hours, this.minutes, this.seconds);
  }
  else if (this.minutes > 0)
  {
  return string.Format(format_4, this.minutes, this.seconds);
  }
  else
  {
  return string.Format(format_5, this.seconds);
  }
  }
 
  public string FormatAsDate()
  {
  string format = "Y{0:#0}, D{1:#0} {2:00}:{3:00}:{4:00.0}s";
 
  return string.Format(format, years + 1, days + 1, hours, minutes, seconds);
  }
 
  public UnpackedTime(int years, int days, int hours, int minutes, double seconds)
  {
  this.years = years;
  this.days = days;
  this.hours = hours;
  this.minutes = minutes;
  this.seconds = seconds;
  }
 
  public UnpackedTime() : this(0, 0, 0, 0, 0d) {}
  }
  #endregion
 
  public static string UppercaseFirst(string s)
  {
  if (string.IsNullOrEmpty(s))
  {
  return string.Empty;
  }
  char[] a = s.ToCharArray();
  a[0] = char.ToUpper(a[0]);
  return new string(a);
  }
 
  //transfer angles
  public static double Nivvy_CalcTransferPhaseAngle(double r_current, double r_target, double grav_param)
  {
  r_target /= 1000;
  r_current /= 1000;
  grav_param /= 1000000000;
 
  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_transfer = (2 * Math.PI) * Math.Sqrt((midpoint * midpoint * midpoint) / grav_param);
  return 360 * (0.5 - (T_transfer / (2 * T_target)));
  }
 
  public static double Younata_DeltaVToGetToOtherBody(double mu, double r1, double r2)
  {
  /*
  def deltaVToGetToOtherBody(mu, r1, r2):
  # mu = gravity param of common orbiting body of r1 and r2
  # (e.g. for mun to minmus, mu is kerbin's gravity param
  # r1 = initial body's orbit radius
  # r2 = target body's orbit radius
 
  # return value is km/s
  sur1 = math.sqrt(mu / r1)
  sr1r2 = math.sqrt(float(2*r2)/float(r1+r2))
  mult = sr1r2 - 1
  return sur1 * mult
  */
  double sur1, sr1r2, mult;
  sur1 = Math.Sqrt(mu / r1);
  sr1r2 = Math.Sqrt((2 * r2) / (r1 + r2));
  mult = sr1r2 - 1;
  return sur1 * mult;
  }
 
  public static double Younata_DeltaVToExitSOI(double mu, double r1, double r2, double v)
  {
  /*
  def deltaVToExitSOI(mu, r1, r2, v):
  # mu = gravity param of current body
  # r1 = current orbit radius
  # r2 = SOI radius
  # v = SOI exit velocity
  foo = r2 * (v**2) - 2 * mu
  bar = r1 * foo + (2 * r2 * mu)
  r = r1*r2
  return math.sqrt(bar / r)
  */
  double foo = r2 * (v * v) - 2 * mu;
  double bar = r1 * foo + (2 * r2 * mu);
  double r = r1 * r2;
  return Math.Sqrt(bar / r);
  }
 
  public static double Younata_TransferBurnPoint(double r, double v, double angle, double mu)
  {
  /*
  def transferBurnPoint(r, v, angle, mu):
  # r = parking orbit radius
  # v = ejection velocity
  # angle = phase angle (from function phaseAngle())
  # mu = gravity param of current body.
  epsilon = ((v**2)/2) - (mu / r)
  h = r * v * math.sin(angle)
  e = math.sqrt(1 + ((2 * epsilon * h**2)/(mu**2)))
  theta = math.acos(1.0 / e)
  degrees = theta * (180.0 / math.pi)
  return 180 - degrees
  */
  double epsilon, h, ee, theta, degrees;
  epsilon = ((v * v) / 2) - (mu / r);
  h = r * v * Math.Sin(angle);
  ee = Math.Sqrt(1 + ((2 * epsilon * (h * h)) / (mu * mu)));
  theta = Math.Acos(1.0 / ee);
  degrees = theta * (180.0 / Math.PI);
  return 180 - degrees;
  // returns the ejection angle
  }
 
  public static double Adammada_CurrrentPhaseAngle(
  double body_LAN,
  double body_orbitPct,
  double origin_LAN,
  double origin_orbitPct
  )
  {
  double angle = (body_LAN / 360 + body_orbitPct) - (origin_LAN / 360 + origin_orbitPct);
  if (angle > 1)
  angle = angle - 1;
  if (angle < 0)
  angle = angle + 1;
  if (angle > 0.5)
  angle = angle - 1;
  angle = angle * 360;
  return angle;
  }
 
  public static double Adammada_CurrentEjectionAngle(
  double vessel_long,
  double origin_rotAngle,
  double origin_LAN,
  double origin_orbitPct
  )
  {
  //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);
 
  while (eangle < 0)
  eangle = eangle + 360;
  while (eangle > 360)
  eangle = eangle - 360;
  if (eangle < 270)
  eangle = 90 - eangle;
  else
  eangle = 450 - eangle;
  return eangle;
  }
 
  public static double mrenigma03_calcphase(Vessel vessel, CelestialBody target) //calculates phase angle between the current body and target body
  {
  Vector3d vecthis = new Vector3d();
  Vector3d vectarget = new Vector3d();
  vectarget = target.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime());
 
  if ((vessel.mainBody.name == "Sun") || (vessel.mainBody.referenceBody.referenceBody.name == "Sun"))
  {
  vecthis = vessel.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime());
  }
  else
  {
  vecthis = vessel.mainBody.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime());
  }
 
  vecthis = Vector3d.Project(new Vector3d(vecthis.x, 0, vecthis.z), vecthis);
  vectarget = Vector3d.Project(new Vector3d(vectarget.x, 0, vectarget.z), vectarget);
 
  Vector3d prograde = new Vector3d();
  prograde = Quaternion.AngleAxis(90, Vector3d.forward) * vecthis;
 
  double phase = Vector3d.Angle(vecthis, vectarget);
 
  if (Vector3d.Angle(prograde, vectarget) > 90)
  phase = 360 - phase;
 
  return (phase + 360) % 360;
  }
 
  public static double adjustCurrPhaseAngle(double transfer_angle, double curr_phase)
  {
  if (transfer_angle < 0)
  {
  if (curr_phase > 0)
  return (-1 * (360 - curr_phase));
  else if (curr_phase < 0)
  return curr_phase;
  }
  else if (transfer_angle > 0)
  {
  if (curr_phase > 0)
  return curr_phase;
  else if (curr_phase < 0)
  return (360 + curr_phase);
  }
  return curr_phase;
  }
 
  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
  // need 0-360 instead
  //
  // ie i have -17 in the screenshot
  // need it to show 343
  //
  // do this
  //
  // if < 0, add curr to 360 // 360 + (-17) = 343
  // else its good as it is
 
  if (curr_ejection < 0)
  return 360 + curr_ejection;
  else
  return curr_ejection;
 
  }
 
  public static double adjust_transfer_ejection_angle(double trans_ejection, double trans_phase)
  {
  // if transfer_phase_angle < 0 its a lower transfer
  //180 + curr_ejection
  // else if transfer_phase_angle > 0 its good as it is
 
  if (trans_phase < 0)
  return 180 + trans_ejection;
  else
  return trans_ejection;
 
  }
 
  public static void display_transfer_angles_SUN2PLANET(CelestialBody body, Vessel vessel)
  {
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label("Phase angle (curr/trans):");
  GUILayout.Label(
  VOID_Tools.mrenigma03_calcphase(vessel, body).ToString("F3") + "° / " + VOID_Tools.Nivvy_CalcTransferPhaseAngle(
  vessel.orbit.semiMajorAxis,
  body.orbit.semiMajorAxis,
  vessel.mainBody.gravParameter
  ).ToString("F3") + "°",
  GUILayout.ExpandWidth(false)
  );
  GUILayout.EndHorizontal();
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label("Transfer velocity:");
  GUILayout.Label(
  (VOID_Tools.Younata_DeltaVToGetToOtherBody(
  (vessel.mainBody.gravParameter / 1000000000),
  (vessel.orbit.semiMajorAxis / 1000),
  (body.orbit.semiMajorAxis / 1000)
  ) * 1000).ToString("F2") + "m/s",
  GUILayout.ExpandWidth(false)
  );
  GUILayout.EndHorizontal();
  }
 
  public static void display_transfer_angles_PLANET2PLANET(CelestialBody body, Vessel vessel)
  {
  double dv1 = VOID_Tools.Younata_DeltaVToGetToOtherBody(
  (vessel.mainBody.referenceBody.gravParameter / 1000000000),
  (vessel.mainBody.orbit.semiMajorAxis / 1000),
  (body.orbit.semiMajorAxis / 1000)
  );
  double dv2 = VOID_Tools.Younata_DeltaVToExitSOI(
  (vessel.mainBody.gravParameter / 1000000000),
  (vessel.orbit.semiMajorAxis / 1000),
  (vessel.mainBody.sphereOfInfluence / 1000),
  Math.Abs(dv1)
  );
 
  double trans_ejection_angle = VOID_Tools.Younata_TransferBurnPoint(
  (vessel.orbit.semiMajorAxis / 1000),
  dv2,
  (Math.PI / 2.0),
  (vessel.mainBody.gravParameter / 1000000000)
  );
  double curr_ejection_angle = VOID_Tools.Adammada_CurrentEjectionAngle(
  FlightGlobals.ActiveVessel.longitude,
  FlightGlobals.ActiveVessel.orbit.referenceBody.rotationAngle,
  FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.LAN,
  FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.orbitPercent
  );
 
  double trans_phase_angle = VOID_Tools.Nivvy_CalcTransferPhaseAngle(
  vessel.mainBody.orbit.semiMajorAxis,
  body.orbit.semiMajorAxis,
  vessel.mainBody.referenceBody.gravParameter
  ) % 360;
  double curr_phase_angle = VOID_Tools.Adammada_CurrrentPhaseAngle(
  body.orbit.LAN,
  body.orbit.orbitPercent,
  FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.LAN,
  FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.orbitPercent
  );
 
  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_curr_ejection_angle = VOID_Tools.adjust_current_ejection_angle(curr_ejection_angle);
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label("Phase angle (curr/trans):");
  GUILayout.Label(
  adj_phase_angle.ToString("F3") + "° / " + trans_phase_angle.ToString("F3") + "°",
  GUILayout.ExpandWidth(false)
  );
  GUILayout.EndHorizontal();
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label("Ejection angle (curr/trans):");
  GUILayout.Label(
  adj_curr_ejection_angle.ToString("F3") + "° / " + adj_trans_ejection_angle.ToString("F3") + "°",
  GUILayout.ExpandWidth(false)
  );
  GUILayout.EndHorizontal();
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label("Transfer velocity:");
  GUILayout.Label((dv2 * 1000).ToString("F2") + "m/s", GUILayout.ExpandWidth(false));
  GUILayout.EndHorizontal();
  }
 
  public static void display_transfer_angles_PLANET2MOON(CelestialBody body, Vessel vessel)
  {
  double dv1 = VOID_Tools.Younata_DeltaVToGetToOtherBody(
  (vessel.mainBody.gravParameter / 1000000000),
  (vessel.orbit.semiMajorAxis / 1000),
  (body.orbit.semiMajorAxis / 1000)
  );
 
  double trans_phase_angle = VOID_Tools.Nivvy_CalcTransferPhaseAngle(
  vessel.orbit.semiMajorAxis,
  body.orbit.semiMajorAxis,
  vessel.mainBody.gravParameter
  );
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label("Phase angle (curr/trans):");
  GUILayout.Label(
  VOID_Tools.mrenigma03_calcphase(vessel, body).ToString("F3") + "° / " + trans_phase_angle.ToString("F3") + "°",
  GUILayout.ExpandWidth(false)
  );
  GUILayout.EndHorizontal();
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label("Transfer velocity:");
  GUILayout.Label((dv1 * 1000).ToString("F2") + "m/s", GUILayout.ExpandWidth(false));
  GUILayout.EndHorizontal();
  }
 
  public static void display_transfer_angles_MOON2MOON(CelestialBody body, Vessel vessel)
  {
  double dv1 = VOID_Tools.Younata_DeltaVToGetToOtherBody(
  (vessel.mainBody.referenceBody.gravParameter / 1000000000),
  (vessel.mainBody.orbit.semiMajorAxis / 1000),
  (body.orbit.semiMajorAxis / 1000)
  );
  double dv2 = VOID_Tools.Younata_DeltaVToExitSOI(
  (vessel.mainBody.gravParameter / 1000000000),
  (vessel.orbit.semiMajorAxis / 1000),
  (vessel.mainBody.sphereOfInfluence / 1000),
  Math.Abs(dv1)
  );
  double trans_ejection_angle = VOID_Tools.Younata_TransferBurnPoint(
  (vessel.orbit.semiMajorAxis / 1000),
  dv2,
  (Math.PI / 2.0),
  (vessel.mainBody.gravParameter / 1000000000)
  );
 
  double curr_phase_angle = VOID_Tools.Adammada_CurrrentPhaseAngle(
  body.orbit.LAN,
  body.orbit.orbitPercent,
  FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.LAN,
  FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.orbitPercent
  );
  double curr_ejection_angle = VOID_Tools.Adammada_CurrentEjectionAngle(
  FlightGlobals.ActiveVessel.longitude,
  FlightGlobals.ActiveVessel.orbit.referenceBody.rotationAngle,
  FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.LAN,
  FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.orbitPercent
  );
 
  double trans_phase_angle = VOID_Tools.Nivvy_CalcTransferPhaseAngle(
  vessel.mainBody.orbit.semiMajorAxis,
  body.orbit.semiMajorAxis,
  vessel.mainBody.referenceBody.gravParameter
  ) % 360;
 
  double adj_phase_angle = VOID_Tools.adjustCurrPhaseAngle(trans_phase_angle, curr_phase_angle);
  //double adj_ejection_angle = adjustCurrEjectionAngle(trans_phase_angle, curr_ejection_angle);
 
  //new stuff
  //
  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);
  //
  //
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label("Phase angle (curr/trans):");
  GUILayout.Label(
  adj_phase_angle.ToString("F3") + "° / " + trans_phase_angle.ToString("F3") + "°",
  GUILayout.ExpandWidth(false)
  );
  GUILayout.EndHorizontal();
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label("Ejection angle (curr/trans):");
  GUILayout.Label(
  adj_curr_ejection_angle.ToString("F3") + "° / " + adj_trans_ejection_angle.ToString("F3") + "°",
  GUILayout.ExpandWidth(false)
  );
  GUILayout.EndHorizontal();
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label("Transfer velocity:");
  GUILayout.Label((dv2 * 1000).ToString("F2") + "m/s", GUILayout.ExpandWidth(false));
  GUILayout.EndHorizontal();
  }
 
  public static string get_heading_text(double heading)
  {
  if (heading > 348.75 || heading <= 11.25)
  return "N";
  else if (heading > 11.25 && heading <= 33.75)
  return "NNE";
  else if (heading > 33.75 && heading <= 56.25)
  return "NE";
  else if (heading > 56.25 && heading <= 78.75)
  return "ENE";
  else if (heading > 78.75 && heading <= 101.25)
  return "E";
  else if (heading > 101.25 && heading <= 123.75)
  return "ESE";
  else if (heading > 123.75 && heading <= 146.25)
  return "SE";
  else if (heading > 146.25 && heading <= 168.75)
  return "SSE";
  else if (heading > 168.75 && heading <= 191.25)
  return "S";
  else if (heading > 191.25 && heading <= 213.75)
  return "SSW";
  else if (heading > 213.75 && heading <= 236.25)
  return "SW";
  else if (heading > 236.25 && heading <= 258.75)
  return "WSW";
  else if (heading > 258.75 && heading <= 281.25)
  return "W";
  else if (heading > 281.25 && heading <= 303.75)
  return "WNW";
  else if (heading > 303.75 && heading <= 326.25)
  return "NW";
  else if (heading > 326.25 && heading <= 348.75)
  return "NNW";
  else
  return "";
  }
  }
 
  public class CBListComparer : IComparer<CelestialBody>
  {
  public int Compare(CelestialBody bodyA, CelestialBody bodyB)
  {
  Tools.PostDebugMessage(this, "got bodyA: {0} & bodyB: {1}", bodyA, bodyB);
 
  if (bodyA == null && bodyB == null)
  {
  Tools.PostDebugMessage(this, "both bodies are null, returning 0");
  return 0;
  }
  if (bodyA == null)
  {
  Tools.PostDebugMessage(this, "bodyA is null, returning -1");
  return -1;
  }
  if (bodyB == null)
  {
  Tools.PostDebugMessage(this, "bodyB is null, returning 1");
  return 1;
  }
 
  Tools.PostDebugMessage(this, "bodies are not null, carrying on");
 
  if (object.ReferenceEquals(bodyA, bodyB))
  {
  Tools.PostDebugMessage(this, "bodies are equal, returning 0");
  return 0;
  }
 
  Tools.PostDebugMessage(this, "bodies are not equal, carrying on");
 
  if (bodyA.orbitDriver == null)
  {
  Tools.PostDebugMessage(this, "bodyA.orbit is null (bodyA is the sun, returning 1");
  return 1;
  }
  if (bodyB.orbitDriver == null)
  {
  Tools.PostDebugMessage(this, "bodyB.orbit is null (bodyB is the sun, returning -1");
  return -1;
  }
 
  Tools.PostDebugMessage(this, "orbits are not null, carrying on");
 
  if (bodyA.orbit.referenceBody == bodyB.orbit.referenceBody)
  {
  Tools.PostDebugMessage(this, "bodies share a parent, comparing SMAs");
  return -bodyA.orbit.semiMajorAxis.CompareTo(bodyB.orbit.semiMajorAxis);
  }
 
  Tools.PostDebugMessage(this, "orbits do not share a parent, carrying on");
 
  if (bodyA.hasAncestor(bodyB))
  {
  Tools.PostDebugMessage(this, "bodyA is a moon or sub-moon of bodyB, returning -1");
  return -1;
  }
  if (bodyB.hasAncestor(bodyA))
  {
  Tools.PostDebugMessage(this, "bodyA is a moon or sub-moon of bodyB, returning 1");
  return 1;
  }
 
  Tools.PostDebugMessage(this, "bodies do not have an obvious relationship, searching for one");
 
  if (VOID_Tools.NearestRelatedParents(ref bodyA, ref bodyB))
  {
  Tools.PostDebugMessage(this, "good relation {0} and {1}, comparing", bodyA.bodyName, bodyB.bodyName);
  return this.Compare(bodyA, bodyB);
  }
 
  Tools.PostDebugMessage(this, "bad relation {0} and {1}, giving up", bodyA.bodyName, bodyB.bodyName);
 
  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} ..\..\..\Games\KSP_win\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} ..\..\..\Games\KSP_win\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} /opt/games/KSP_linux/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} /opt/games/KSP_linux/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="IVOID_Module.cs" />  
<Compile Include="VOIDFlightMaster.cs" />  
<Compile Include="VOID_Core.cs" />  
<Compile Include="VOID_Module.cs" />  
<Compile Include="VOID_HUD.cs" /> <Compile Include="VOID_HUD.cs" />
<Compile Include="VOID_SaveValue.cs" />  
<Compile Include="VOID_Orbital.cs" /> <Compile Include="VOID_Orbital.cs" />
<Compile Include="VOID_SurfAtmo.cs" /> <Compile Include="VOID_SurfAtmo.cs" />
<Compile Include="VOID_VesselInfo.cs" /> <Compile Include="VOID_VesselInfo.cs" />
<Compile Include="VOID_Transfer.cs" /> <Compile Include="VOID_Transfer.cs" />
<Compile Include="VOID_CBInfoBrowser.cs" /> <Compile Include="VOID_CBInfoBrowser.cs" />
<Compile Include="VOID_Rendezvous.cs" /> <Compile Include="VOID_Rendezvous.cs" />
<Compile Include="VOID_VesselRegister.cs" /> <Compile Include="VOID_VesselRegister.cs" />
<Compile Include="VOID_DataLogger.cs" /> <Compile Include="VOID_DataLogger.cs" />
<Compile Include="VOID_EditorCore.cs" />  
<Compile Include="VOID_EditorHUD.cs" /> <Compile Include="VOID_EditorHUD.cs" />
<Compile Include="VOID_DataValue.cs" />  
<Compile Include="VOIDEditorMaster.cs" />  
<Compile Include="VOID_Tools.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_EditorTWR.cs" /> <Compile Include="VOID_TWR.cs" />
  <Compile Include="VOID_CareerStatus.cs" />
  <Compile Include="VOID_StageInfo.cs" />
  <Compile Include="VOID_Styles.cs" />
  <Compile Include="VOID_Data.cs" />
  <Compile Include="VOIDMaster_Flight.cs" />
  <Compile Include="VOIDMaster_Editor.cs" />
  <Compile Include="VOIDMaster_SpaceCentre.cs" />
  <Compile Include="VOIDCore_SpaceCentre.cs" />
  <Compile Include="VOIDCore_Flight.cs" />
  <Compile Include="VOIDCore_Editor.cs" />
  <Compile Include="VOIDCore_Generic.cs" />
  <Compile Include="API\IVOID_Module.cs" />
  <Compile Include="API\VOIDCore.cs" />
  <Compile Include="API\IVOID_SaveValue.cs" />
  <Compile Include="API\IVOID_DataValue.cs" />
  <Compile Include="API\VOID_Module.cs" />
  <Compile Include="Tools\VOID_Tools.cs" />
  <Compile Include="Tools\VOID_DataValue.cs" />
  <Compile Include="Tools\VOID_SaveValue.cs" />
  <Compile Include="API\VOID_HUDModule.cs" />
  <Compile Include="API\Attributes\VOID_ScenesAttribute.cs" />
  <Compile Include="API\Attributes\AVOID_SaveValue.cs" />
  <Compile Include="API\VOIDMaster.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>
  <None Include="GameData\VOID\Textures\ATM_VOID.cfg" />
  </ItemGroup>
  <ItemGroup>
  <Folder Include="API\" />
  <Folder Include="Tools\" />
  <Folder Include="API\Attributes\" />
  </ItemGroup>
</Project> </Project>
   
  // VOID
  //
  // VOID_EditorCore.cs
  //
  // Copyright © 2014, toadicus
  // All rights reserved.
  //
  // Redistribution and use in source and binary forms, with or without modification,
  // are permitted provided that the following conditions are met:
  //
  // 1. Redistributions of source code must retain the above copyright notice,
  // this list of conditions and the following disclaimer.
  //
  // 2. Redistributions in binary form must reproduce the above copyright notice,
  // this list of conditions and the following disclaimer in the documentation and/or other
  // materials provided with the distribution.
  //
  // 3. Neither the name of the copyright holder nor the names of its contributors may be used
  // to endorse or promote products derived from this software without specific prior written permission.
  //
  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
  using KerbalEngineer.VesselSimulator;
  using KSP;
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using ToadicusTools;
  using UnityEngine;
 
  namespace VOID
  {
  [VOID_Scenes(GameScenes.EDITOR)]
  public class VOIDCore_Editor : VOIDCore_Generic<VOIDCore_Editor>
  {
  public override void FixedUpdate() {}
  }
  }
 
 
  // VOID
  //
  // VOIDCore_Flight.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 UnityEngine;
  using ToadicusTools;
 
  namespace VOID
  {
  [VOID_Scenes(GameScenes.FLIGHT)]
  public class VOIDCore_Flight : VOIDCore_Generic<VOIDCore_Flight>
  {
  public override void DrawConfigurables()
  {
  if (HighLogic.LoadedSceneIsFlight)
  {
  this.consumeResource.value = GUITools.Toggle(this.consumeResource, "Consume Resources");
  }
 
  base.DrawConfigurables();
  }
  }
  }
 
 
  // VOID
  //
  // VOIDCore_Generic.cs
  //
  // Copyright © 2014, toadicus
  // All rights reserved.
  //
  // Redistribution and use in source and binary forms, with or without modification,
  // are permitted provided that the following conditions are met:
  //
  // 1. Redistributions of source code must retain the above copyright notice,
  // this list of conditions and the following disclaimer.
  //
  // 2. Redistributions in binary form must reproduce the above copyright notice,
  // this list of conditions and the following disclaimer in the documentation and/or other
  // materials provided with the distribution.
  //
  // 3. Neither the name of the copyright holder nor the names of its contributors may be used
  // to endorse or promote products derived from this software without specific prior written permission.
  //
  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
  using KerbalEngineer.VesselSimulator;
  using KSP;
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using ToadicusTools;
  using UnityEngine;
 
  namespace VOID
  {
  public abstract class VOIDCore_Generic<T> : VOID_SingletonCore<T>, IVOID_Module, IDisposable
  where T : VOID_Module, new()
  {
  /*
  * Fields
  * */
  protected string VoidName = "VOID";
  protected string VoidVersion;
 
  [AVOID_SaveValue("configValue")]
  protected VOID_SaveValue<int> configVersion = (VOID_SaveValue<int>)VOIDCore.CONFIG_VERSION;
 
  protected List<IVOID_Module> modules = new List<IVOID_Module>();
  protected bool modulesLoaded = false;
 
  protected Texture2D VOIDIconTexture;
  protected string VOIDIconOnActivePath;
  protected string VOIDIconOnInactivePath;
  protected string VOIDIconOffActivePath;
  protected string VOIDIconOffInactivePath;
 
  private bool _useToolbarManager;
 
  protected GUIStyle iconStyle;
 
  protected int windowBaseID = -96518722;
  protected int windowID = 0;
 
  protected bool GUIStylesLoaded = false;
 
  protected CelestialBody homeBody;
 
  [AVOID_SaveValue("togglePower")]
  public VOID_SaveValue<bool> togglePower = (VOID_SaveValue<bool>)true;
 
  public override bool powerAvailable { get; protected set; }
 
  [AVOID_SaveValue("consumeResource")]
  protected VOID_SaveValue<bool> consumeResource = (VOID_SaveValue<bool>)false;
 
  [AVOID_SaveValue("resourceName")]
  protected VOID_SaveValue<string> resourceName = (VOID_SaveValue<string>)"ElectricCharge";
 
  [AVOID_SaveValue("resourceRate")]
  protected VOID_SaveValue<float> resourceRate = (VOID_SaveValue<float>)0.2f;
 
  [AVOID_SaveValue("updatePeriod")]
  protected VOID_SaveValue<double> updatePeriod = (VOID_SaveValue<double>)(1001f / 15000f);
  protected string stringFrequency;
 
  [AVOID_SaveValue("vesselSimActive")]
  protected VOID_SaveValue<bool> vesselSimActive;
 
  [AVOID_SaveValue("timeScaleFlags")]
  protected VOID_SaveValue<UInt32> timeScaleFlags;
 
  // Vessel Type Housekeeping
  protected bool vesselTypesLoaded = false;
 
  protected string defaultSkin = "KSP window 2";
 
  [AVOID_SaveValue("defaultSkin")]
  protected VOID_SaveValue<string> skinName;
  protected int skinIdx;
 
  protected Dictionary<string, GUISkin> validSkins;
  protected string[] skinNames;
  protected string[] forbiddenSkins =
  {
  "PlaqueDialogSkin",
  "FlagBrowserSkin",
  "SSUITextAreaDefault",
  "ExperimentsDialogSkin",
  "ExpRecoveryDialogSkin",
  "KSP window 1",
  "KSP window 3",
  "KSP window 5",
  "KSP window 6",
  "PartTooltipSkin",
  "KSCContextMenuSkin"
  };
  protected bool skinsLoaded = false;
 
  public override bool configDirty { get; set; }
 
  protected IButton ToolbarButton;
  protected ApplicationLauncherButton AppLauncherButton;
  protected IconState iconState;
 
  /*
  * Properties
  * */
  public override bool Active
  {
  get
  {
  return base.Active;
  }
  set
  {
  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;
  protected set;
  }
 
  public override int ConfigVersion
  {
  get
  {
  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
  {
  get
  {
  if (this.skinsLoaded)
  {
  try
  {
  return this.validSkins[this.skinName];
  }
  catch
  {
  }
  }
 
  return AssetBase.GetGUISkin(this.defaultSkin);
  }
  }
 
  public override List<CelestialBody> SortedBodyList
  {
  get;
  protected set;
  }
 
  public override double UpdatePeriod
  {
  get
  {
  return this.updatePeriod;
  }
  }
 
  public override float UpdateTimer
  {
  get;
  protected set;
  }
 
  public override int WindowID
  {
  get
  {
  if (this.windowID == 0)
  {
  this.windowID = this.windowBaseID;
  }
  return this.windowID++;
  }
  }
 
  public override Stage[] Stages
  {
  get;
  protected set;
  }
 
  public override Stage LastStage
  {
  get;
  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
  {
  get
  {
  if (this.togglePower && this.powerAvailable)
  {
  return IconState.PowerOn;
  }
  else
  {
  return IconState.PowerOff;
  }
 
  }
  }
 
  protected virtual ApplicationLauncher.AppScenes appIconVisibleScenes
  {
  get
  {
  return HighLogic.LoadedScene.ToAppScenes();
  }
  }
 
  protected bool useToolbarManager
  {
  get
  {
  return _useToolbarManager & ToolbarManager.ToolbarAvailable;
  }
  set
  {
  if (_useToolbarManager == value)
  {
  return;
  }
 
  if (value == false && this.ToolbarButton != null)
  {
  this.ToolbarButton.Destroy();
  this.ToolbarButton = null;
  }
  if (value == true)
  {
  if (this.AppLauncherButton != null)
  {
  ApplicationLauncher.Instance.RemoveModApplication(this.AppLauncherButton);
  this.AppLauncherButton = null;
  }
 
  this.InitializeToolbarButton();
  }
 
  _useToolbarManager = value;
  }
  }
 
  /*
  * Events
  * */
  public override event VOIDEventHandler onApplicationQuit;
  public override event VOIDEventHandler onSkinChanged;
 
  /*
  * Methods
  * */
  public override void DrawGUI()
  {
  this.windowID = this.windowBaseID;
 
  if (!this.modulesLoaded)
  {
  this.LoadModulesOfType<IVOID_Module>();
  }
 
  if (!this.skinsLoaded)
  {
  this.LoadSkins();
  }
 
  GUI.skin = this.Skin;
 
  if (!this.GUIStylesLoaded)
  {
  this.LoadGUIStyles();
 
  Tools.PostDebugMessage(
  this,
  "ToolbarAvailable: {0}, UseToobarManager: {1}",
  ToolbarManager.ToolbarAvailable,
  this.useToolbarManager);
  }
 
  if (!this.useToolbarManager)
  {
  if (this.AppLauncherButton == null)
  {
  Tools.PostDebugMessage(this,
  "UseToolbarManager = false (ToolbarAvailable = {0}) and " +
  "AppLauncherButton is null, making AppLauncher button.",
  ToolbarManager.ToolbarAvailable
  );
  this.InitializeAppLauncherButton();
  }
  }
  else if (this.ToolbarButton == null)
  {
  Tools.PostDebugMessage(this,
  "UseToolbarManager = true (ToolbarAvailable = {0}) and " +
  "ToolbarButton is null, making Toolbar button.",
  ToolbarManager.ToolbarAvailable
  );
  this.InitializeToolbarButton();
  }
 
  this.SetIconTexture();
 
  if (this.Active)
  {
  base.DrawGUI();
  }
  }
 
  public virtual void Update()
  {
  this.LoadBeforeUpdate();
 
  if (
  this.vesselSimActive &&
  (
  this.Vessel != null ||
  (
  HighLogic.LoadedSceneIsEditor &&
  EditorLogic.RootPart != null &&
  EditorLogic.SortedShipList.Count > 0
  )
  )
  )
  {
  Tools.PostDebugMessage(this, "Updating SimManager.");
  this.UpdateSimManager();
  }
 
  if (!this.GUIRunning)
  {
  this.StartGUI();
  }
 
  foreach (IVOID_Module module in this.modules)
  {
  if (
  !module.GUIRunning &&
  module.Active &&
  module.InValidScene &&
  (
  !HighLogic.LoadedSceneIsEditor ||
  (EditorLogic.RootPart != null && EditorLogic.SortedShipList.Count > 0)
  )
  )
  {
  module.StartGUI();
  }
  if (
  module.GUIRunning &&
  (
  !module.Active ||
  !this.togglePower ||
  !module.InValidScene ||
  this.FactoryReset ||
  (
  HighLogic.LoadedSceneIsEditor &&
  (EditorLogic.RootPart == null || EditorLogic.SortedShipList.Count == 0)
  )
  )
  )
  {
  module.StopGUI();
  }
 
  if (module is IVOID_BehaviorModule)
  {
  ((IVOID_BehaviorModule)module).Update();
  }
  }
 
  this.CheckAndSave();
  this.UpdateTimer += Time.deltaTime;
  }
 
  public virtual void FixedUpdate()
  {
  bool newPowerState = this.powerAvailable;
 
  if (this.togglePower && this.consumeResource &&
  this.Vessel.vesselType != VesselType.EVA &&
  TimeWarp.deltaTime != 0)
  {
  float powerReceived = this.Vessel.rootPart.RequestResource(
  this.resourceName,
  this.resourceRate * TimeWarp.fixedDeltaTime
  );
 
  if (powerReceived > 0)
  {
  newPowerState = true;
  }
  else
  {
  newPowerState = false;
  }
 
  if (this.powerAvailable != newPowerState)
  {
  this.powerAvailable = newPowerState;
  }
  }
 
  foreach (IVOID_Module module in this.modules)
  {
  if (module is IVOID_BehaviorModule)
  {
  ((IVOID_BehaviorModule)module).FixedUpdate();
  }
  }
  }
 
  public void OnDestroy()
  {
  foreach (IVOID_Module module in this.modules)
  {
  if (module is IVOID_BehaviorModule)
  {
  ((IVOID_BehaviorModule)module).OnDestroy();
  }
  }
 
  this.Dispose();
  }
 
  public virtual void OnApplicationQuit()
  {
  if (this.onApplicationQuit != null)
  {
  this.onApplicationQuit(this);
  }
 
  this.OnDestroy();
  }
 
  public override void StartGUI()
  {
  if (!this.GUIRunning)
  {
  RenderingManager.AddToPostDrawQueue(3, this.DrawGUI);
  }
  }
 
  public void ResetGUI()
  {
  this.StopGUI();
 
  foreach (IVOID_Module module in this.modules)
  {
  module.StopGUI();
  module.StartGUI();
  }
 
  this.StartGUI();
  }
 
  public override void ModuleWindow(int id)
  {
  GUILayout.BeginVertical();
 
  if (this.powerAvailable || !HighLogic.LoadedSceneIsFlight)
  {
  if (!HighLogic.LoadedSceneIsEditor)
  {
  string str = string.Intern("ON");
  if (togglePower)
  str = string.Intern("OFF");
  if (GUILayout.Button("Power " + str))
  {
  togglePower.value = !togglePower;
  }
  }
 
  if (togglePower || !HighLogic.LoadedSceneIsFlight)
  {
  foreach (IVOID_Module module in this.modules)
  {
  if (module is VOID_ConfigWindow)
  {
  continue;
  }
 
  module.Active = GUITools.Toggle(module.Active, module.Name);
  }
  }
  }
  else
  {
  GUILayout.Label("-- POWER LOST --", VOID_Styles.labelRed);
  }
 
  VOID_ConfigWindow.Instance.Active = GUITools.Toggle(
  VOID_ConfigWindow.Instance.Active,
  "Configuration"
  );
 
  GUILayout.EndVertical();
 
  base.ModuleWindow(id);
  }
 
  public override void DrawConfigurables()
  {
  GUIContent _content;
 
  this.useToolbarManager = GUITools.Toggle(this.useToolbarManager, "Use Blizzy's Toolbar If Available");
 
  this.vesselSimActive.value = GUITools.Toggle(this.vesselSimActive.value,
  "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.Label("Skin:", GUILayout.ExpandWidth(false));
 
  _content = new GUIContent();
 
  _content.text = "◄";
  _content.tooltip = "Select previous skin";
  if (GUILayout.Button(_content, GUILayout.ExpandWidth(true)))
  {
  this.skinIdx--;
  Tools.PostDebugMessage(string.Format(
  "{0}: new this.skinIdx = {1} :: skin_list.Count = {2}",
  this.GetType().Name,
  this.skinName,
  this.validSkins.Count
  ));
  }
 
  _content.text = this.Skin.name;
  _content.tooltip = "Current skin";
  GUILayout.Label(_content, VOID_Styles.labelCenter, GUILayout.ExpandWidth(true));
 
  _content.text = "►";
  _content.tooltip = "Select next skin";
  if (GUILayout.Button(_content, GUILayout.ExpandWidth(true)))
  {
  this.skinIdx++;
  Tools.PostDebugMessage(string.Format(
  "{0}: new this.skinIdx = {1} :: skin_list.Count = {2}",
  this.GetType().Name,
  this.skinName,
  this.validSkins.Count
  ));
  }
 
  this.skinIdx %= this.skinNames.Length;
  if (this.skinIdx < 0)
  {
  this.skinIdx += this.skinNames.Length;
  }
 
  if (this.skinName != skinNames[this.skinIdx])
  {
  this.skinName.value = skinNames[this.skinIdx];
  this.GUIStylesLoaded = false;
  }
 
  GUILayout.EndHorizontal();
 
  GUILayout.BeginHorizontal();
  GUILayout.Label("Update Rate (Hz):");
  if (this.stringFrequency == null)
  {
  this.stringFrequency = (1f / this.UpdatePeriod).ToString();
  }
  this.stringFrequency = GUILayout.TextField(this.stringFrequency.ToString(), 5, GUILayout.ExpandWidth(true));
 
  if (GUILayout.Button("Apply"))
  {
  double updateFreq = 1f / this.UpdatePeriod;
  double.TryParse(stringFrequency, out updateFreq);
  this.updatePeriod.value = 1 / updateFreq;
  }
  GUILayout.EndHorizontal();
 
  foreach (IVOID_Module mod in this.modules)
  {
  mod.DrawConfigurables();
  }
 
  this.FactoryReset = GUITools.Toggle(this.FactoryReset, "Factory Reset");
  }
 
  protected void UpdateSimManager()
  {
  if (SimManager.ResultsReady())
  {
  if (HighLogic.LoadedSceneIsEditor)
  {
  SimManager.Gravity = VOID_Data.KerbinGee;
  }
  else
  {
  double radius = this.Vessel.Radius();
  SimManager.Gravity = this.Vessel.mainBody.gravParameter / (radius * radius);
  }
 
  SimManager.minSimTime = new TimeSpan(0, 0, 0, 0, (int)(this.UpdatePeriod * 1000d));
 
  SimManager.TryStartSimulation();
  }
  #if DEBUG
  else
  {
  Tools.PostDebugMessage(this, "VesselSimulator results not ready.");
  }
  #endif
  }
 
  protected void 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>()
  {
  Tools.DebugLogger sb = Tools.DebugLogger.New(this);
  sb.AppendLine("Loading modules...");
 
  foreach (AssemblyLoader.LoadedAssembly assy in AssemblyLoader.loadedAssemblies)
  {
  foreach (Type loadedType in assy.assembly.GetExportedTypes())
  {
  if (
  loadedType.IsInterface ||
  loadedType.IsAbstract ||
  !typeof(U).IsAssignableFrom(loadedType) ||
  typeof(VOIDCore).IsAssignableFrom(loadedType)
  )
  {
  continue;
  }
 
  sb.AppendFormat("Checking IVOID_Module type {0}...", loadedType.Name);
 
  try
  {
  this.LoadModule(loadedType);
  sb.AppendLine("Success.");
  }
  catch (Exception ex)
  {
  sb.AppendFormat("Failed, caught {0}\n", ex.GetType().Name);
 
  #if DEBUG
  Debug.LogException(ex);
  #endif
  }
  }
  }
 
  this.modulesLoaded = true;
 
  sb.AppendFormat("Loaded {0} modules.\n", this.Modules.Count);
 
  sb.Print();
  }
 
  protected void LoadModule(Type T)
  {
  var existingModules = this.modules.Where(mod => mod.GetType().Name == T.Name);
  if (existingModules.Any())
  {
  Tools.PostDebugMessage(string.Format(
  "{0}: refusing to load {1}: already loaded",
  this.GetType().Name,
  T.Name
  ));
  return;
  }
 
  var InstanceProperty = T.GetProperty(
  "Instance",
  System.Reflection.BindingFlags.Static |
  System.Reflection.BindingFlags.Public |
  System.Reflection.BindingFlags.FlattenHierarchy
  );
 
  object modInstance = null;
  IVOID_Module module;
 
  if (InstanceProperty != null)
  {
  modInstance = InstanceProperty.GetValue(null, null);
  }
 
  if (modInstance != null)
  {
  module = modInstance as IVOID_Module;
  }
  else
  {
  module = Activator.CreateInstance(T) as IVOID_Module;
  }
 
  if (module.InValidGame && module.InValidScene)
  {
  module.LoadConfig();
  this.modules.Add(module);
 
  Tools.PostDebugMessage(string.Format(
  "{0}: loaded module {1}.",
  this.GetType().Name,
  T.Name
  ));
  }
  else
  {
  if (module is IDisposable)
  {
  (module as IDisposable).Dispose();
  }
  }
  }
 
  protected void LoadSkins()
  {
  Tools.PostDebugMessage("AssetBase has skins: \n" +
  string.Join("\n\t",
  Resources.FindObjectsOfTypeAll(typeof(GUISkin))
  .Select(s => s.ToString())
  .ToArray()
  )
  );
 
  this.validSkins = Resources.FindObjectsOfTypeAll(typeof(GUISkin))
  .Where(s => !this.forbiddenSkins.Contains(s.name))
  .Select(s => s as GUISkin)
  .GroupBy(s => s.name)
  .Select(g => g.First())
  .ToDictionary(s => s.name);
 
  Tools.PostDebugMessage(string.Format(
  "{0}: loaded {1} GUISkins.",
  this.GetType().Name,
  this.validSkins.Count
  ));
 
  this.skinNames = this.validSkins.Keys.ToArray();
  Array.Sort(this.skinNames);
 
  int defaultIdx = int.MinValue;
 
  for (int i = 0; i < this.skinNames.Length; i++)
  {
  if (this.skinNames[i] == this.skinName)
  {
  this.skinIdx = i;
  }
  if (this.skinNames[i] == this.defaultSkin)
  {
  defaultIdx = i;
  }
  if (this.skinIdx != int.MinValue && defaultIdx != int.MinValue)
  {
  break;
  }
  }
 
  if (this.skinIdx == int.MinValue)
  {
  this.skinIdx = defaultIdx;
  }
 
  Tools.PostDebugMessage(string.Format(
  "{0}: _skinIdx = {1}.",
  this.GetType().Name,
  this.skinName.ToString()
  ));
 
  this.skinsLoaded = true;
  }
 
  protected void LoadGUIStyles()
  {
  VOID_Styles.OnSkinChanged();
 
  if (this.onSkinChanged != null)
  {
  this.onSkinChanged(this);
  }
 
  this.GUIStylesLoaded = true;
  }
 
  protected void LoadVesselTypes()
  {
  this.AllVesselTypes = Enum.GetValues(typeof(VesselType)).OfType<VesselType>().ToArray();
  this.vesselTypesLoaded = true;
  }
 
  protected void LoadBeforeUpdate()
  {
  if (!this.vesselTypesLoaded)
  {
  this.LoadVesselTypes();
  }
 
  if (this.SortedBodyList == null && FlightGlobals.Bodies != null && FlightGlobals.Bodies.Count > 0)
  {
  this.SortedBodyList = new List<CelestialBody>(FlightGlobals.Bodies);
  this.SortedBodyList.Sort(new CBListComparer());
  this.SortedBodyList.Reverse();
 
  Debug.Log(string.Format("sortedBodyList: {0}", string.Join("\n\t", this.SortedBodyList.Select(b => b.bodyName).ToArray())));
  }
 
  }
 
  protected void InitializeToolbarButton()
  {
  // Do nothing if (the Toolbar is not available.
  if (!ToolbarManager.ToolbarAvailable)
  {
  Tools.PostDebugMessage(this, "Refusing to make a ToolbarButton: ToolbarAvailable = false");
  return;
  }
 
  this.ToolbarButton = ToolbarManager.Instance.add(this.VoidName, "coreToggle");
  this.ToolbarButton.Text = this.VoidName;
  this.SetIconTexture(this.powerState | this.activeState);
 
  this.ToolbarButton.Visible = true;
 
  this.ToolbarButton.OnClick +=
  (e) =>
  {
  this.ToggleMainWindow();
  };
 
  Tools.PostDebugMessage(string.Format("{0}: Toolbar Button initialized.", this.GetType().Name));
  }
 
  protected void InitializeAppLauncherButton()
  {
  if (ApplicationLauncher.Ready)
  {
  this.AppLauncherButton = ApplicationLauncher.Instance.AddModApplication(
  this.ToggleMainWindow, this.ToggleMainWindow,
  this.appIconVisibleScenes,
  this.VOIDIconTexture
  );
 
  Tools.PostDebugMessage(
  this,
  "AppLauncherButton initialized in {0}",
  Enum.GetName(
  typeof(GameScenes),
  HighLogic.LoadedScene
  )
  );
  }
  }
 
  protected void ToggleMainWindow()
  {
  this.Active = !this.Active;
  }
 
  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)
  {
  switch (state)
  {
  case (IconState.PowerOff | IconState.Inactive):
  this.SetIconTexture(this.VOIDIconOffInactivePath);
  break;
  case (IconState.PowerOff | IconState.Active):
  this.SetIconTexture(this.VOIDIconOffActivePath);
  break;
  case (IconState.PowerOn | IconState.Inactive):
  this.SetIconTexture(this.VOIDIconOnInactivePath);
  break;
  case (IconState.PowerOn | IconState.Active):
  this.SetIconTexture(this.VOIDIconOnActivePath);
  break;
  default:
  throw new NotImplementedException();
  }
  }
 
  protected void SetIconTexture(string texturePath)
  {
  if (texturePath == null)
  {
  return;
  }
 
  if (this.ToolbarButton != null)
  {
  this.ToolbarButton.TexturePath = texturePath;
  }
 
  if (this.AppLauncherButton != null)
  {
  this.VOIDIconTexture = GameDatabase.Instance.GetTexture(texturePath.Replace("icon", "appIcon"), false);
 
  this.AppLauncherButton.SetTexture(VOIDIconTexture);
  }
  }
 
  protected virtual void CheckAndSave()
  {
  this.saveTimer += Time.deltaTime;
 
  if (this.saveTimer > 2f)
  {
  if (!this.configDirty)
  {
  return;
  }
 
  Tools.PostDebugMessage(string.Format(
  "{0}: Time to save, checking if configDirty: {1}",
  this.GetType().Name,
  this.configDirty
  ));
 
  this.SaveConfig();
  this.saveTimer = 0;
  }
  }
 
  public override void LoadConfig()
  {
  base.LoadConfig();
 
  foreach (IVOID_Module module in this.modules)
  {
  module.LoadConfig();
  }
 
  this.TimeScale |= GameSettings.KERBIN_TIME ? VOID_TimeScale.KERBIN_TIME : 0u;
  }
 
  public override void SaveConfig()
  {
  if (this.configNeedsUpdate && this is VOIDCore_Flight)
  {
  KSP.IO.File.Delete<T>("config.xml");
  }
 
  var config = KSP.IO.PluginConfiguration.CreateForType<T>();
 
  config.load();
 
  this.Save(config);
 
  foreach (IVOID_Module module in this.modules)
  {
  module.Save(config);
  }
 
  config.save();
 
  this.configDirty = false;
  }
 
  public VOIDCore_Generic()
  {
  System.Version version = this.GetType().Assembly.GetName().Version;
 
  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.Active = true;
 
  this.skinName = (VOID_SaveValue<string>)this.defaultSkin;
  this.skinIdx = int.MinValue;
 
  this.VOIDIconOnActivePath = "VOID/Textures/void_icon_light_glow";
  this.VOIDIconOnInactivePath = "VOID/Textures/void_icon_dark_glow";
  this.VOIDIconOffActivePath = "VOID/Textures/void_icon_light";
  this.VOIDIconOffInactivePath = "VOID/Textures/void_icon_dark";
 
  this.saveTimer = 0f;
  this.UpdateTimer = 0f;
 
  this.vesselSimActive = (VOID_SaveValue<bool>)true;
  SimManager.Atmosphere = 0d;
  SimManager.OnReady += this.GetSimManagerResults;
 
  this.useToolbarManager = ToolbarManager.ToolbarAvailable;
 
  this.LoadConfig();
 
  this.configVersion = (VOID_SaveValue<int>)VOIDCore.CONFIG_VERSION;
 
  this.FactoryReset = false;
  }
 
  public override void Dispose()
  {
  this.StopGUI();
 
  this.onSkinChanged(this);
 
  if (this.AppLauncherButton != null)
  {
  ApplicationLauncher.Instance.RemoveModApplication(this.AppLauncherButton);
  this.AppLauncherButton = null;
  }
  if (this.ToolbarButton != null)
  {
  this.ToolbarButton.Destroy();
  this.ToolbarButton = null;
  }
 
  _instance = null;
  _initialized = false;
  }
  }
  }
 
  // VOID
  //
  // VOIDCore_SpaceCentre.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
  {
  [VOID_Scenes(GameScenes.SPACECENTER)]
  public class VOIDCore_SpaceCentre : VOIDCore_Generic<VOIDCore_SpaceCentre>
  {
  public override void FixedUpdate() {}
  }
  }
 
 
file:a/VOIDEditorMaster.cs (deleted)
// VOID  
//  
// VOIDEditorMaster.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.  
//  
///////////////////////////////////////////////////////////////////////////////  
//  
// Much, much credit to Younata, Adammada, Nivvydaskrl and to all the authors  
// behind MechJeb, RemoteTech Relay Network, ISA MapSat, and Protractor for some  
// invaluable functions and making your nicely written code available to learn from.  
//  
///////////////////////////////////////////////////////////////////////////////  
//  
// This software uses VesselSimulator and Engineer.Extensions from Engineer Redux.  
// Engineer Redux (c) 2013 cybutek  
// Used by permission.  
//  
///////////////////////////////////////////////////////////////////////////////  
 
using Engineer.VesselSimulator;  
using KSP;  
using System;  
using ToadicusTools;  
using UnityEngine;  
 
namespace VOID  
{  
[KSPAddon(KSPAddon.Startup.EditorAny, false)]  
public class VOIDEditorMaster : MonoBehaviour  
{  
protected VOID_EditorCore Core;  
 
public void Awake()  
{  
Tools.PostDebugMessage ("VOIDEditorMaster: Waking up.");  
this.Core = VOID_EditorCore.Instance;  
this.Core.ResetGUI ();  
Tools.PostDebugMessage ("VOIDEditorMaster: Awake.");  
}  
 
public void Update()  
{  
if (!HighLogic.LoadedSceneIsEditor && this.Core != null)  
{  
this.Core.SaveConfig ();  
this.Core = null;  
VOID_EditorCore.Reset();  
return;  
}  
 
if (this.Core == null)  
{  
this.Awake();  
}  
 
this.Core.Update ();  
 
if (this.Core.factoryReset)  
{  
KSP.IO.File.Delete<VOID_EditorCore>("config.xml");  
this.Core = null;  
VOID_EditorCore.Reset();  
}  
}  
 
public void FixedUpdate()  
{  
if (this.Core == null || !HighLogic.LoadedSceneIsEditor)  
{  
return;  
}  
 
this.Core.FixedUpdate ();  
}  
 
public void OnGUI()  
{  
if (this.Core == null)  
{  
return;  
}  
 
this.Core.OnGUI();  
}  
}  
}  
 
file:a/VOIDFlightMaster.cs (deleted)
// VOID  
//  
// VOIDFlightMaster.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.  
//  
///////////////////////////////////////////////////////////////////////////////  
//  
// Much, much credit to Younata, Adammada, Nivvydaskrl and to all the authors  
// behind MechJeb, RemoteTech Relay Network, ISA MapSat, and Protractor for some  
// invaluable functions and making your nicely written code available to learn from.  
//  
///////////////////////////////////////////////////////////////////////////////  
//  
// This software uses VesselSimulator and Engineer.Extensions from Engineer Redux.  
// Engineer Redux (c) 2013 cybutek  
// Used by permission.  
//  
///////////////////////////////////////////////////////////////////////////////  
 
using System;  
using UnityEngine;  
using Engineer.VesselSimulator;  
using ToadicusTools;  
 
namespace VOID  
{  
[KSPAddon(KSPAddon.Startup.Flight, false)]  
public class VOIDFlightMaster : MonoBehaviour  
{  
protected VOID_Core Core;  
 
public void Awake()  
{  
Tools.PostDebugMessage ("VOIDFlightMaster: Waking up.");  
this.Core = (VOID_Core)VOID_Core.Instance;  
this.Core.ResetGUI ();  
Tools.PostDebugMessage ("VOIDFlightMaster: Awake.");  
}  
 
public void Update()  
{  
if (!HighLogic.LoadedSceneIsFlight && this.Core != null)  
{  
this.Core.SaveConfig ();  
this.Core = null;  
VOID_Core.Reset();  
return;  
}  
 
if (this.Core == null)  
{  
this.Awake();  
}  
 
this.Core.Update ();  
 
if (this.Core.factoryReset)  
{  
KSP.IO.File.Delete<VOID_Core>("config.xml");  
this.Core = null;  
VOID_Core.Reset();  
}  
}  
 
public void FixedUpdate()  
{  
if (this.Core == null || !HighLogic.LoadedSceneIsFlight)  
{  
return;  
}  
 
this.Core.FixedUpdate ();  
}  
 
public void OnGUI()  
{  
if (this.Core == null)  
{  
return;  
}  
 
this.Core.OnGUI();  
}  
}  
}  
 
  // VOID
  //
  // VOIDEditorMaster.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.
  //
  ///////////////////////////////////////////////////////////////////////////////
  //
  // Much, much credit to Younata, Adammada, Nivvydaskrl and to all the authors
  // behind MechJeb, RemoteTech Relay Network, ISA MapSat, and Protractor for some
  // invaluable functions and making your nicely written code available to learn from.
  //
  ///////////////////////////////////////////////////////////////////////////////
  //
  // This software uses VesselSimulator and Engineer.Extensions from Engineer Redux.
  // Engineer Redux (c) 2013 cybutek
  // Used by permission.
  //
  ///////////////////////////////////////////////////////////////////////////////
 
  using KerbalEngineer.VesselSimulator;
  using KSP;
  using System;
  using ToadicusTools;
  using UnityEngine;
 
  namespace VOID
  {
  [KSPAddon(KSPAddon.Startup.EditorAny, false)]
  public class VOIDMaster_Editor : VOIDMaster<VOIDCore_Editor>
  {
  public override void Awake()
  {
  Tools.PostDebugMessage ("VOIDEditorMaster: Waking up.");
  this.Core = VOIDCore_Editor.Instance;
  this.Core.ResetGUI ();
  Tools.PostDebugMessage ("VOIDEditorMaster: Awake.");
  }
  }
  }
 
  // VOID
  //
  // VOIDFlightMaster.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.
  //
  ///////////////////////////////////////////////////////////////////////////////
  //
  // Much, much credit to Younata, Adammada, Nivvydaskrl and to all the authors
  // behind MechJeb, RemoteTech Relay Network, ISA MapSat, and Protractor for some
  // invaluable functions and making your nicely written code available to learn from.
  //
  ///////////////////////////////////////////////////////////////////////////////
  //
  // This software uses VesselSimulator and Engineer.Extensions from Engineer Redux.
  // Engineer Redux (c) 2013 cybutek
  // Used by permission.
  //
  ///////////////////////////////////////////////////////////////////////////////
 
  using System;
  using UnityEngine;
  using KerbalEngineer.VesselSimulator;
  using ToadicusTools;
 
  namespace VOID
  {
  [KSPAddon(KSPAddon.Startup.Flight, false)]
  public class VOIDMaster_Flight : VOIDMaster<VOIDCore_Flight>
  {
  public override void Awake()
  {
  this.LogDebug("Waking up.");
  this.Core = VOIDCore_Flight.Instance;
  this.Core.ResetGUI ();
  this.LogDebug("Awake.");
  }
  }
  }
 
  // VOID
  //
  // VOIDFlightMaster.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.
  //
  ///////////////////////////////////////////////////////////////////////////////
  //
  // Much, much credit to Younata, Adammada, Nivvydaskrl and to all the authors
  // behind MechJeb, RemoteTech Relay Network, ISA MapSat, and Protractor for some
  // invaluable functions and making your nicely written code available to learn from.
  //
  ///////////////////////////////////////////////////////////////////////////////
  //
  // This software uses VesselSimulator and Engineer.Extensions from Engineer Redux.
  // Engineer Redux (c) 2013 cybutek
  // Used by permission.
  //
  ///////////////////////////////////////////////////////////////////////////////
 
  using System;
  using UnityEngine;
  using KerbalEngineer.VesselSimulator;
  using ToadicusTools;
 
  namespace VOID
  {
  [KSPAddon(KSPAddon.Startup.SpaceCentre, false)]
  public class VOIDMaster_SpaceCentre : VOIDMaster<VOIDCore_SpaceCentre>
  {
  public override void Awake()
  {
  this.LogDebug("Waking up.");
  this.Core = VOIDCore_SpaceCentre.Instance;
  this.Core.ResetGUI ();
  this.LogDebug("Awake.");
  }
  }
  }
 
// 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")]
  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 = VOID_Core.Instance.allBodies[selectedBodyIdx1]; selectedBody1 = this.core.AllBodies[selectedBodyIdx1];
selectedBody2 = VOID_Core.Instance.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 = VOID_Core.Instance.allBodies.Count - 1; if (selectedBodyIdx1 < 0)
} {
GUILayout.Label(VOID_Core.Instance.allBodies[selectedBodyIdx1].bodyName, VOID_Core.Instance.LabelStyles["center_bold"], 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 > VOID_Core.Instance.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 = VOID_Core.Instance.allBodies.Count - 1; if (selectedBodyIdx2 < 0)
} {
GUILayout.Label(VOID_Core.Instance.allBodies[selectedBodyIdx2].bodyName, VOID_Core.Instance.LabelStyles["center_bold"], 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 > VOID_Core.Instance.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();
} }
   
GUI.DragWindow(); if (GUILayout.Button("Scientific Parameters", GUILayout.ExpandWidth(true)))
  {
  toggleScience.value = !toggleScience;
  }
   
  if (toggleScience)
  {
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
   
  //begin physical info value label column
  GUILayout.BeginVertical(GUILayout.Width(150));
   
   
  /*
  * public float RecoveryValue = 1f;
   
  public float InSpaceHighDataValue = 1f;
   
  public float spaceAltitudeThreshold = 250000f;
   
  public float flyingAltitudeThreshold = 18000f;
   
  public float InSpaceLowDataValue = 1f;
   
  public float SplashedDataValue = 1f;
   
  public float LandedDataValue = 1f;
   
  public float FlyingHighDataValue = 1f;
   
  public float FlyingLowDataValue = 1f;
  */
   
  GUILayout.Label("Surface Multiplier:");
  GUILayout.Label("Ocean Multiplier:");
  GUILayout.Label("Flying-Low Multiplier:");
  GUILayout.Label("Flying-High Multiplier:");
  GUILayout.Label("Low Orbit Multiplier:");
  GUILayout.Label("High Orbit Multiplier:");
  GUILayout.Label("'Flying-High' Altitude:");
  GUILayout.Label("'High Orbit' Altitude:");
  GUILayout.Label("Recovery Multiplier:");
   
  //end physical info value label column
  GUILayout.EndVertical();
   
  //begin primary physical values column
  GUILayout.BeginVertical(GUILayout.Width(150));
   
  this.cbColumnScience(selectedBody1);
   
  //end primary physical column
  GUILayout.EndVertical();
   
  //begin secondary physical values column
  GUILayout.BeginVertical(GUILayout.Width(150));
   
  this.cbColumnScience(selectedBody2);
   
  //end target physical values column
  GUILayout.EndVertical();
   
  //end physical value horizontal chunk
  GUILayout.EndHorizontal();
  }
   
  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_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
else GUILayout.Label((body.orbit.ApA / 1000).ToString("##,#") + "km", VOID_Core.Instance.LabelStyles["right"], 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_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
else GUILayout.Label(VOID_Tools.ConvertInterval(body.orbit.timeToAp), VOID_Core.Instance.LabelStyles["right"], 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_Core.Instance.LabelStyles["right"], 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_Core.Instance.LabelStyles["right"], 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_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
else GUILayout.Label(VOID_Tools.ConvertInterval(body.orbit.timeToPe), VOID_Core.Instance.LabelStyles["right"], 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_Core.Instance.LabelStyles["right"], 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_Core.Instance.LabelStyles["right"], 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_Core.Instance.LabelStyles["right"], 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_Core.Instance.LabelStyles["right"], 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_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
else GUILayout.Label(VOID_Tools.ConvertInterval(body.orbit.period), VOID_Core.Instance.LabelStyles["right"], 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_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
else GUILayout.Label(VOID_Tools.ConvertInterval(body.rotationPeriod), VOID_Core.Instance.LabelStyles["right"], 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_Core.Instance.LabelStyles["right"], 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_Core.Instance.LabelStyles["right"], 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_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
else GUILayout.Label((body.orbit.meanAnomaly * 180d / Math.PI).ToString("F3") + "°", VOID_Core.Instance.LabelStyles["right"], 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_Core.Instance.LabelStyles["right"], 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_Core.Instance.LabelStyles["right"], 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_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
else GUILayout.Label((body.orbit.eccentricAnomaly * 180d / Math.PI).ToString("F3") + "°", VOID_Core.Instance.LabelStyles["right"], 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_Core.Instance.LabelStyles["right"], 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_Core.Instance.LabelStyles["right"], 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_Core.Instance.LabelStyles["right"], 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_Core.Instance.LabelStyles["right"], 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_Core.Instance.LabelStyles["right"], 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_Core.Instance.LabelStyles["right"], 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_Core.Instance.LabelStyles["right"], 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_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); GUILayout.Label(body_tidally_locked, VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
} }
} }
   
private void body_OP_show_physical_info(CelestialBody body) private void body_OP_show_physical_info(CelestialBody body)
{ {
   
GUILayout.Label((body.Radius / 1000).ToString("##,#") + "km", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); GUILayout.Label((body.Radius / 1000).ToString("##,#") + "km", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
   
GUILayout.Label((((body.Radius * body.Radius) * 4 * Math.PI) / 1000).ToString("0.00e+00") + "km²", VOID_Core.Instance.LabelStyles["right"], 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_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); GUILayout.Label((((4d / 3) * Math.PI * (body.Radius * body.Radius * body.Radius)) / 1000).ToString("0.00e+00") + "km³", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
   
GUILayout.Label(body.Mass.ToString("0.00e+00") + "kg", VOID_Core.Instance.LabelStyles["right"], 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_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); GUILayout.Label(p.ToString("##,#") + "kg/m³", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
   
if (body.bodyName == "Sun") GUILayout.Label(Tools.MuMech_ToSI(body.sphereOfInfluence), VOID_Core.Instance.LabelStyles["right"], 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_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); else GUILayout.Label(Tools.MuMech_ToSI(body.sphereOfInfluence), VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
   
GUILayout.Label(body.orbitingBodies.Count.ToString(), VOID_Core.Instance.LabelStyles["right"], 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_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); GUILayout.Label(num_art_sats.ToString(), VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
   
double g_ASL = (VOID_Core.Constant_G * body.Mass) / (body.Radius * body.Radius); double g_ASL = (VOIDCore.Constant_G * body.Mass) / (body.Radius * body.Radius);
   
GUILayout.Label(Tools.MuMech_ToSI(g_ASL) + "m/s²", VOID_Core.Instance.LabelStyles["right"], 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_Core.Instance.LabelStyles["right"], 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_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); GUILayout.Label(O2, VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
} }
else else
{ {
GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], 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_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); GUILayout.Label(ocean, VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
  }
   
  private void cbColumnScience(CelestialBody body)
  {
  /*GUILayout.Label("Surface Science Multiplier:");
  GUILayout.Label("Ocean Science Multiplier:");
  GUILayout.Label("Low-Atmosphere Science Multiplier:");
  GUILayout.Label("High-Atmosphere Science Multiplier:");
  GUILayout.Label("Low Orbit Science Multiplier:");
  GUILayout.Label("High Orbit Science Multiplier:");
  GUILayout.Label("'In Space' Altitude:");
  GUILayout.Label("'Flying' Altitude:");
  GUILayout.Label("Recovery Multiplier:");*/
   
  var scienceValues = body.scienceValues;
   
  GUILayout.Label(scienceValues.LandedDataValue.ToString("0.0#"),
  VOID_Styles.labelRight,
  GUILayout.ExpandWidth(true));
   
  GUILayout.Label(
  body.ocean ? scienceValues.SplashedDataValue.ToString("0.0#") : "N/A",
  VOID_Styles.labelRight,
  GUILayout.ExpandWidth(true));
   
  GUILayout.Label(
  body.atmosphere ? scienceValues.FlyingLowDataValue.ToString("0.0#") : "N/A",
  VOID_Styles.labelRight,
  GUILayout.ExpandWidth(true));
   
  GUILayout.Label(
  body.atmosphere ? scienceValues.FlyingHighDataValue.ToString("0.0#") : "N/A",
  VOID_Styles.labelRight,
  GUILayout.ExpandWidth(true));
   
  GUILayout.Label(scienceValues.InSpaceLowDataValue.ToString("0.0#"),
  VOID_Styles.labelRight,
  GUILayout.ExpandWidth(true));
   
  GUILayout.Label(scienceValues.InSpaceHighDataValue.ToString("0.0#"),
  VOID_Styles.labelRight,
  GUILayout.ExpandWidth(true));
   
  GUILayout.Label(
  body.atmosphere ? scienceValues.flyingAltitudeThreshold.ToString("N0") : "N/A",
  VOID_Styles.labelRight,
  GUILayout.ExpandWidth(true));
   
  GUILayout.Label(
  scienceValues.spaceAltitudeThreshold.ToString("N0"),
  VOID_Styles.labelRight,
  GUILayout.ExpandWidth(true));
   
  GUILayout.Label(scienceValues.RecoveryValue.ToString("0.0#"),
  VOID_Styles.labelRight,
  GUILayout.ExpandWidth(true));
} }
} }
} }
  // VOID
  //
  // VOID_CareerStatus.cs
  //
  // Copyright © 2014, toadicus
  // All rights reserved.
  //
  // Redistribution and use in source and binary forms, with or without modification,
  // are permitted provided that the following conditions are met:
  //
  // 1. Redistributions of source code must retain the above copyright notice,
  // this list of conditions and the following disclaimer.
  //
  // 2. Redistributions in binary form must reproduce the above copyright notice,
  // this list of conditions and the following disclaimer in the documentation and/or other
  // materials provided with the distribution.
  //
  // 3. Neither the name of the copyright holder nor the names of its contributors may be used
  // to endorse or promote products derived from this software without specific prior written permission.
  //
  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
  using KSP;
  using System;
  using System.Text;
  using ToadicusTools;
  using UnityEngine;
 
  namespace VOID
  {
  [VOID_Scenes(GameScenes.FLIGHT, GameScenes.EDITOR, GameScenes.SPACECENTER)]
  [VOID_GameModes(Game.Modes.CAREER, Game.Modes.SCIENCE_SANDBOX)]
  public class VOID_CareerStatus : VOID_SingletonWindow<VOID_CareerStatus>
  {
  public static string formatDelta(double delta, string numberFormat)
  {
  if (delta > 0)
  {
  return string.Format("<color='lime'>{0}↑</color>", delta.ToString(numberFormat, Tools.SIFormatter));
  }
  else if (delta < 0)
  {
  return string.Format("<color='red'>{0}↓</color>", delta.ToString(numberFormat, Tools.SIFormatter));
  }
  else
  {
  return "0";
  }
  }
 
  public static string formatDelta(double delta)
  {
  return formatDelta(delta, "#,##0.##");
  }
 
  public static string formatDelta(float delta)
  {
  return formatDelta((double)delta);
  }
 
  private GUIContent fundsContent;
  private GUIContent repContent;
  private GUIContent scienceContent;
 
  #pragma warning disable 0414
  private Texture2D fundsIconGreen;
  private Texture2D fundsIconRed;
  private Texture2D reputationIconGreen;
  private Texture2D reputationIconRed;
  private Texture2D scienceIcon;
  #pragma warning restore 0414
 
  public double lastFundsChange
  {
  get;
  private set;
  }
 
  public float lastRepChange
  {
  get;
  private set;
  }
 
  public float lastScienceChange
  {
  get;
  private set;
  }
 
  public double currentFunds
  {
  get;
  private set;
  }
 
  public float currentReputation
  {
  get;
  private set;
  }
 
  public float currentScience
  {
  get;
  private set;
  }
 
  private bool currenciesInitialized
  {
  get
  {
  Tools.PostDebugMessage(
  this,
  "Checking init state:" +
  "\n\tcurrentFunds={0}" +
  "\n\tcurrentScience={1}" +
  "\n\tcurrentReputation={2}",
  this.currentFunds,
  this.currentScience,
  this.currentReputation
  );
 
  return !(
  double.IsNaN(this.currentFunds) ||
  float.IsNaN(this.currentScience) ||
  float.IsNaN(this.currentReputation)
  );
  }
  }
 
  public override void DrawGUI()
  {
  if (Event.current.type != EventType.Layout && !this.currenciesInitialized)
  {
  this.initCurrencies();
  }
 
  base.DrawGUI();
  }
 
  public override void ModuleWindow(int id)
  {
  GUILayout.BeginVertical();
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label(VOID_Data.fundingStatus.Label);
  GUILayout.FlexibleSpace();
  this.fundsContent.text = VOID_Data.fundingStatus.Value;
  GUILayout.Label(this.fundsContent, GUILayout.ExpandWidth(true));
  GUILayout.EndHorizontal();
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label(VOID_Data.reputationStatus.Label);
  GUILayout.FlexibleSpace();
  this.repContent.text = VOID_Data.reputationStatus.Value;
  GUILayout.Label(this.repContent, GUILayout.ExpandWidth(true));
  GUILayout.EndHorizontal();
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label(VOID_Data.scienceStatus.Label);
  GUILayout.FlexibleSpace();
  this.scienceContent.text = VOID_Data.scienceStatus.Value;
  GUILayout.Label(this.scienceContent, GUILayout.ExpandWidth(true));
  GUILayout.EndHorizontal();
 
  GUILayout.EndVertical();
 
  base.ModuleWindow(id);
  }
 
  // TODO: Update event handlers to do something useful with the new "reasons" parameter.
  private void onFundsChange(double newValue, TransactionReasons reasons)
  {
  this.lastFundsChange = newValue - this.currentFunds;
  this.currentFunds = newValue;
  }
 
  private void onRepChange(float newValue, TransactionReasons reasons)
  {
  this.lastRepChange = newValue - this.currentReputation;
  this.currentReputation = newValue;
  }
 
  private void onScienceChange(float newValue, TransactionReasons reasons)
  {
  this.lastScienceChange = newValue - this.currentScience;
  this.currentScience = newValue;
  }
 
  private void onGameStateLoad(ConfigNode node)
  {
  this.initCurrencies();
  }
 
  private void initCurrencies()
  {
  Tools.PostDebugMessage(
  this,
  "Initializing currencies." +
  "\n\tFunding.Instance={0}" +
  "ResearchAndDevelopment.Instance={1}" +
  "Reputation.Instance={2}",
  Funding.Instance == null ? "NULL" : Funding.Instance.ToString(),
  ResearchAndDevelopment.Instance == null ? "NULL" : ResearchAndDevelopment.Instance.ToString(),
  Reputation.Instance == null ? "NULL" : Reputation.Instance.ToString()
  );
 
  this.currentFunds = Funding.Instance != null ? Funding.Instance.Funds : double.NaN;
  this.currentReputation = Reputation.Instance != null ? Reputation.Instance.reputation : float.NaN;
  this.currentScience = ResearchAndDevelopment.Instance != null ?
  ResearchAndDevelopment.Instance.Science : float.NaN;
  }
 
  /*
  * MissionRecoveryDialog::fundsIconGreen.name: UiElements_05
  * MissionRecoveryDialog::fundsIconRed.name: UiElements_06
  * MissionRecoveryDialog::reputationIconGreen.name: UiElements_07
  * MissionRecoveryDialog::reputationIconRed.name: UiElements_08
  * MissionRecoveryDialog::scienceIcon.name: UiElements_12
  * */
  public VOID_CareerStatus() : base()
  {
  this.Name = "Career Status";
 
  GameEvents.OnFundsChanged.Add(this.onFundsChange);
  GameEvents.OnReputationChanged.Add(this.onRepChange);
  GameEvents.OnScienceChanged.Add(this.onScienceChange);
  GameEvents.onGameStateLoad.Add(this.onGameStateLoad);
 
  bool texturesLoaded;
 
  texturesLoaded = IOTools.LoadTexture(out this.fundsIconGreen, "VOID/Textures/fundsgreen.png", 10, 18);
  texturesLoaded &= IOTools.LoadTexture(out this.fundsIconRed, "VOID/Textures/fundsred.png", 10, 18);
  texturesLoaded &= IOTools.LoadTexture(out this.reputationIconGreen, "VOID/Textures/repgreen.png", 16, 18);
  texturesLoaded &= IOTools.LoadTexture(out this.reputationIconRed, "VOID/Textures/repred.png", 16, 18);
  texturesLoaded &= IOTools.LoadTexture(out this.scienceIcon, "VOID/Textures/science.png", 16, 18);
 
  this.fundsContent = new GUIContent();
  this.repContent = new GUIContent();
  this.scienceContent = new GUIContent();
 
  if (texturesLoaded)
  {
  this.fundsContent.image = this.fundsIconGreen;
  this.repContent.image = this.reputationIconGreen;
  this.scienceContent.image = this.scienceIcon;
  }
 
  this.currentFunds = double.NaN;
  this.currentScience = float.NaN;
  this.currentReputation = float.NaN;
  }
 
  public override void Dispose()
  {
  GameEvents.OnFundsChanged.Remove(this.onFundsChange);
  GameEvents.OnReputationChanged.Remove(this.onRepChange);
  GameEvents.OnScienceChanged.Remove(this.onScienceChange);
  GameEvents.onGameStateLoad.Remove(this.onGameStateLoad);
 
  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();
  }
  }
  }
 
file:a/VOID_Core.cs (deleted)
// VOID  
//  
// VOID_Core.cs  
//  
// Copyright © 2014, toadicus  
// All rights reserved.  
//  
// Redistribution and use in source and binary forms, with or without modification,  
// are permitted provided that the following conditions are met:  
//  
// 1. Redistributions of source code must retain the above copyright notice,  
// this list of conditions and the following disclaimer.  
//  
// 2. Redistributions in binary form must reproduce the above copyright notice,  
// this list of conditions and the following disclaimer in the documentation and/or other  
// materials provided with the distribution.  
//  
// 3. Neither the name of the copyright holder nor the names of its contributors may be used  
// to endorse or promote products derived from this software without specific prior written permission.  
//  
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,  
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE  
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,  
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR  
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE  
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
 
using Engineer.VesselSimulator;  
using KSP;  
using System;  
using System.Collections.Generic;  
using System.Linq;  
using ToadicusTools;  
using UnityEngine;  
 
namespace VOID  
{  
public class VOID_Core : VOID_Module, IVOID_Module  
{  
#region Singleton Members  
/*  
* Static Members  
* */  
protected static bool _initialized = false;  
 
public static bool Initialized  
{  
get  
{  
return _initialized;  
}  
}  
 
protected static VOID_Core _instance;  
 
public static VOID_Core Instance  
{  
get  
{  
if (_instance == null)  
{  
_instance = new VOID_Core();  
_initialized = true;  
}  
return _instance;  
}  
}  
 
public static void Reset()  
{  
_instance.StopGUI();  
_instance = null;  
_initialized = false;  
}  
#endregion  
 
public static double Constant_G = 6.674e-11;  
 
/*  
* Fields  
* */  
protected string VoidName = "VOID";  
protected string VoidVersion;  
 
protected bool _factoryReset = false;  
 
[AVOID_SaveValue("configValue")]  
protected VOID_SaveValue<int> configVersion = 1;  
 
protected List<IVOID_Module> _modules = new List<IVOID_Module>();  
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;  
[AVOID_SaveValue("VOIDIconPos")]  
protected VOID_SaveValue<Rect> VOIDIconPos = new Rect(Screen.width / 2 - 200, Screen.height - 32, 32f, 32f);  
 
protected Texture2D VOIDIconTexture;  
protected string VOIDIconOnActivePath;  
protected string VOIDIconOnInactivePath;  
protected string VOIDIconOffActivePath;  
protected string VOIDIconOffInactivePath;  
 
protected bool VOIDIconLocked = true;  
 
protected GUIStyle iconStyle;  
 
protected int windowBaseID = -96518722;  
protected int _windowID = 0;  
 
protected bool GUIStylesLoaded = false;  
protected Dictionary<string, GUIStyle> _LabelStyles = new Dictionary<string, GUIStyle>();  
 
protected CelestialBody _Kerbin;  
 
[AVOID_SaveValue("togglePower")]  
public VOID_SaveValue<bool> togglePower = true;  
public bool powerAvailable = true;  
 
[AVOID_SaveValue("consumeResource")]  
protected VOID_SaveValue<bool> consumeResource = false;  
 
[AVOID_SaveValue("resourceName")]  
protected VOID_SaveValue<string> resourceName = "ElectricCharge";  
 
[AVOID_SaveValue("resourceRate")]  
protected VOID_SaveValue<float> resourceRate = 0.2f;  
 
[AVOID_SaveValue("updatePeriod")]  
protected VOID_SaveValue<double> _updatePeriod = 1001f / 15000f;  
protected float _updateTimer = 0f;  
protected string stringFrequency;  
 
[AVOID_SaveValue("vesselSimActive")]  
protected VOID_SaveValue<bool> vesselSimActive;  
 
// Vessel Type Housekeeping  
protected List<VesselType> _allVesselTypes = new List<VesselType>();  
protected bool vesselTypesLoaded = false;  
public float saveTimer = 0;  
 
protected string defaultSkin = "KSP window 2";  
 
[AVOID_SaveValue("defaultSkin")]  
protected VOID_SaveValue<string> _skinName;  
protected int _skinIdx;  
 
protected Dictionary<string, GUISkin> validSkins;  
protected string[] skinNames;  
protected string[] forbiddenSkins =  
{  
"PlaqueDialogSkin",  
"FlagBrowserSkin",  
"SSUITextAreaDefault",  
"ExperimentsDialogSkin",  
"ExpRecoveryDialogSkin",  
"KSP window 5",  
"KSP window 6",  
"PartTooltipSkin"  
};  
protected bool skinsLoaded = false;  
 
public bool configDirty;  
 
[AVOID_SaveValue("UseBlizzyToolbar")]  
protected VOID_SaveValue<bool> _UseToolbarManager;  
internal IButton ToolbarButton;  
 
/*  
* Properties  
* */  
public bool factoryReset  
{  
get  
{  
return this._factoryReset;  
}  
}  
 
public List<IVOID_Module> Modules  
{  
get  
{  
return this._modules;  
}  
}  
 
public GUISkin Skin  
{  
get  
{  
if (this.skinsLoaded)  
{  
try  
{  
return this.validSkins[this._skinName];  
}  
catch  
{  
}  
}  
 
return AssetBase.GetGUISkin(this.defaultSkin);  
}  
}  
 
public int windowID  
{  
get  
{  
if (this._windowID == 0)  
{  
this._windowID = this.windowBaseID;  
}  
return this._windowID++;  
}  
}  
 
public Dictionary<string, GUIStyle> LabelStyles  
{  
get  
{  
return this._LabelStyles;  
}  
}  
 
public List<CelestialBody> allBodies  
{  
get  
{  
return FlightGlobals.Bodies;  
}  
}  
 
public CelestialBody Kerbin  
{  
get  
{  
if (this._Kerbin == null)  
{  
if (FlightGlobals.Bodies != null)  
{  
this._Kerbin = FlightGlobals.Bodies.First(b => b.name == "Kerbin");  
}  
}  
 
return this._Kerbin;  
}  
}  
 
public List<VesselType> allVesselTypes  
{  
get  
{  
return this._allVesselTypes;  
}  
}  
 
public float updateTimer  
{  
get  
{  
return this._updateTimer;  
}  
}  
 
public double updatePeriod  
{  
get  
{  
return this._updatePeriod;  
}  
}  
 
protected IconState powerState  
{  
get  
{  
if (this.togglePower && this.powerAvailable)  
{  
return IconState.PowerOn;  
}  
else  
{  
return IconState.PowerOff;  
}  
 
}  
}  
 
protected IconState activeState  
{  
get  
{  
if (this.mainGuiMinimized)  
{  
return IconState.Inactive;  
}  
else  
{  
return IconState.Active;  
}  
 
}  
}  
 
protected bool UseToolbarManager  
{  
get  
{  
return _UseToolbarManager & ToolbarManager.ToolbarAvailable;  
}  
set  
{  
if (this._UseToolbarManager == value)  
{  
return;  
}  
 
if (value == false && this.ToolbarButton != null)  
{  
this.ToolbarButton.Destroy();  
this.ToolbarButton = null;  
}  
if (value == true)  
{  
this.InitializeToolbarButton();  
}  
 
_UseToolbarManager.value = value;  
}  
}  
 
/*  
* Methods  
* */  
public override void DrawGUI()  
{  
this._windowID = this.windowBaseID;  
 
if (!this._modulesLoaded)  
{  
this.LoadModulesOfType<IVOID_Module>();  
}  
 
if (!this.skinsLoaded)  
{  
this.LoadSkins();  
}  
 
GUI.skin = this.Skin;  
 
if (!this.GUIStylesLoaded)  
{  
this.LoadGUIStyles();  
}  
 
if (!this.UseToolbarManager)  
{  
if (GUI.Button(VOIDIconPos, VOIDIconTexture, this.iconStyle) && this.VOIDIconLocked)  
{  
this.ToggleMainWindow();  
}  
}  
else if (this.ToolbarButton == null)  
{  
this.InitializeToolbarButton();  
}  
 
if (!this.mainGuiMinimized)  
{  
 
Rect _mainWindowPos = this.mainWindowPos;  
 
_mainWindowPos = GUILayout.Window(  
this.windowID,  
_mainWindowPos,  
this.VOIDMainWindow,  
string.Join(" ", new string[] { this.VoidName, this.VoidVersion }),  
GUILayout.Width(250),  
GUILayout.Height(50)  
);  
 
_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,  
this.VOIDConfigWindow,  
string.Join(" ", new string[] { this.VoidName, "Configuration" }),  
GUILayout.Width(250),  
GUILayout.Height(50)  
);  
 
_configWindowPos = Tools.ClampRectToScreen(_configWindowPos);  
 
if (_configWindowPos != this.configWindowPos)  
{  
this.configWindowPos = _configWindowPos;  
}  
}  
}  
 
public void OnGUI()  
{  
if (Event.current.type == EventType.Repaint)  
{  
return;  
}  
 
/*  
Tools.PostDebugMessage(string.Format(  
"Event.current.type: {0}" +  
"\nthis.VOIDIconLocked: {1}" +  
"\nEvent.current.mousePosition: {2}" +  
"\nVOIDIconPos: ({3}, {4}),({5}, {6})",  
Event.current.type,  
this.VOIDIconLocked,  
Event.current.mousePosition,  
this.VOIDIconPos.value.xMin,  
this.VOIDIconPos.value.yMin,  
this.VOIDIconPos.value.xMax,  
this.VOIDIconPos.value.yMax  
));  
*/  
 
if (!this.VOIDIconLocked &&  
VOIDIconPos.value.Contains(Event.current.mousePosition)  
&& Event.current.type == EventType.mouseDrag)  
{  
Tools.PostDebugMessage(string.Format(  
"Event.current.type: {0}" +  
"\ndelta.x: {1}; delta.y: {2}",  
Event.current.type,  
Event.current.delta.x,  
Event.current.delta.y  
));  
 
Rect tmp = new Rect(VOIDIconPos);  
 
tmp.x = Event.current.mousePosition.x - tmp.width / 2;  
tmp.y = Event.current.mousePosition.y - tmp.height / 2;  
 
if (tmp.x > Screen.width - tmp.width)  
{  
tmp.x = Screen.width - tmp.width;  
}  
 
if (tmp.y > Screen.height - tmp.height)  
{  
tmp.y = Screen.height - tmp.height;  
}  
 
VOIDIconPos = tmp;  
}  
}  
 
public void Update()  
{  
this.LoadBeforeUpdate();  
 
if (this.vessel != null && this.vesselSimActive)  
{  
double radius = VOID_Core.Instance.vessel.Radius();  
SimManager.Gravity = VOID_Core.Instance.vessel.mainBody.gravParameter /  
(radius * radius);  
SimManager.TryStartSimulation();  
}  
else if (!this.vesselSimActive)  
{  
SimManager.ClearResults();  
}  
 
if (!this.guiRunning)  
{  
this.StartGUI();  
}  
 
if (!HighLogic.LoadedSceneIsFlight && this.guiRunning)  
{  
this.StopGUI();  
}  
 
foreach (IVOID_Module module in this.Modules)  
{  
if (!module.guiRunning && module.toggleActive)  
{  
module.StartGUI();  
}  
if (module.guiRunning && !module.toggleActive ||  
!this.togglePower ||  
!HighLogic.LoadedSceneIsFlight ||  
this.factoryReset)  
{  
module.StopGUI();  
}  
 
if (module is IVOID_BehaviorModule)  
{  
((IVOID_BehaviorModule)module).Update();  
}  
}  
 
this.CheckAndSave();  
this._updateTimer += Time.deltaTime;  
}  
 
public void FixedUpdate()  
{  
bool newPowerState = this.powerAvailable;  
 
if (this.togglePower && this.consumeResource &&  
this.vessel.vesselType != VesselType.EVA &&  
TimeWarp.deltaTime != 0)  
{  
float powerReceived = this.vessel.rootPart.RequestResource(  
this.resourceName,  
this.resourceRate * TimeWarp.fixedDeltaTime  
);  
 
if (powerReceived > 0)  
{  
newPowerState = true;  
}  
else  
{  
newPowerState = false;  
}  
 
if (this.powerAvailable != newPowerState)  
{  
this.powerAvailable = newPowerState;  
this.SetIconTexture(this.powerState | this.activeState);  
}  
}  
 
foreach (IVOID_BehaviorModule module in  
this._modules.OfType<IVOID_BehaviorModule>().Where(m => !m.GetType().IsAbstract))  
{  
module.FixedUpdate();  
}  
}  
 
public void ResetGUI()  
{  
this.StopGUI();  
 
foreach (IVOID_Module module in this.Modules)  
{  
module.StopGUI();  
module.StartGUI();  
}  
 
this.StartGUI();  
}  
 
public void VOIDMainWindow(int _)  
{  
GUILayout.BeginVertical();  
 
if (this.powerAvailable || HighLogic.LoadedSceneIsEditor)  
{  
if (!HighLogic.LoadedSceneIsEditor)  
{  
string str = string.Intern("ON");  
if (togglePower)  
str = string.Intern("OFF");  
if (GUILayout.Button("Power " + str))  
{  
togglePower.value = !togglePower;  
this.SetIconTexture(this.powerState | this.activeState);  
}  
}  
 
if (togglePower || HighLogic.LoadedSceneIsEditor)  
{  
foreach (IVOID_Module module in this.Modules)  
{  
module.toggleActive = GUILayout.Toggle(module.toggleActive, module.Name);  
}  
}  
}  
else  
{  
GUILayout.Label("-- POWER LOST --", this.LabelStyles["red"]);  
}  
 
this.configWindowMinimized.value = !GUILayout.Toggle(!this.configWindowMinimized, "Configuration");  
 
GUILayout.EndVertical();  
GUI.DragWindow();  
}  
 
public void VOIDConfigWindow(int _)  
{  
GUILayout.BeginVertical();  
 
this.DrawConfigurables();  
 
GUILayout.EndVertical();  
GUI.DragWindow();  
}  
 
public override void DrawConfigurables()  
{  
GUIContent _content;  
 
if (HighLogic.LoadedSceneIsFlight)  
{  
this.consumeResource.value = GUILayout.Toggle(this.consumeResource, "Consume Resources");  
 
this.VOIDIconLocked = GUILayout.Toggle(this.VOIDIconLocked, "Lock Icon Position");  
}  
 
this.UseToolbarManager = GUILayout.Toggle(this.UseToolbarManager, "Use Blizzy's Toolbar If Available");  
 
this.vesselSimActive.value = GUILayout.Toggle(this.vesselSimActive.value,  
"Enable Engineering Calculations");  
 
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
 
GUILayout.Label("Skin:", GUILayout.ExpandWidth(false));  
 
_content = new GUIContent();  
 
_content.text = "◄";  
_content.tooltip = "Select previous skin";  
if (GUILayout.Button(_content, GUILayout.ExpandWidth(true)))  
{  
this.GUIStylesLoaded = false;  
this._skinIdx--;  
Tools.PostDebugMessage(string.Format(  
"{0}: new this._skinIdx = {1} :: skin_list.Count = {2}",  
this.GetType().Name,  
this._skinName,  
this.validSkins.Count  
));  
}  
 
_content.text = this.Skin.name;  
_content.tooltip = "Current skin";  
GUILayout.Label(_content, this.LabelStyles["center"], GUILayout.ExpandWidth(true));  
 
_content.text = "►";  
_content.tooltip = "Select next skin";  
if (GUILayout.Button(_content, GUILayout.ExpandWidth(true)))  
{  
this.GUIStylesLoaded = false;  
this._skinIdx++;  
Tools.PostDebugMessage(string.Format(  
"{0}: new this._skinIdx = {1} :: skin_list.Count = {2}",  
this.GetType().Name,  
this._skinName,  
this.validSkins.Count  
));  
}  
 
this._skinIdx %= this.skinNames.Length;  
if (this._skinIdx < 0)  
{  
this._skinIdx += this.skinNames.Length;  
}  
 
if (this._skinName != skinNames[this._skinIdx])  
{  
this._skinName.value = skinNames[this._skinIdx];  
}  
 
GUILayout.EndHorizontal();  
 
GUILayout.BeginHorizontal();  
GUILayout.Label("Update Rate (Hz):");  
if (this.stringFrequency == null)  
{  
this.stringFrequency = (1f / this.updatePeriod).ToString();  
}  
this.stringFrequency = GUILayout.TextField(this.stringFrequency.ToString(), 5, GUILayout.ExpandWidth(true));  
// GUILayout.FlexibleSpace();  
if (GUILayout.Button("Apply"))  
{  
double updateFreq = 1f / this.updatePeriod;  
double.TryParse(stringFrequency, out updateFreq);  
this._updatePeriod = 1 / updateFreq;  
}  
GUILayout.EndHorizontal();  
 
foreach (IVOID_Module mod in this.Modules)  
{  
mod.DrawConfigurables();  
}  
 
this._factoryReset = GUILayout.Toggle(this._factoryReset, "Factory Reset");  
}  
 
protected void LoadModulesOfType<T>()  
{  
var types = AssemblyLoader.loadedAssemblies  
.Select(a => a.assembly.GetExportedTypes())  
.SelectMany(t => t)  
.Where(v => typeof(T).IsAssignableFrom(v)  
&& !(v.IsInterface || v.IsAbstract) &&  
!typeof(VOID_Core).IsAssignableFrom(v)  
);  
 
Tools.PostDebugMessage(string.Format(  
"{0}: Found {1} modules to check.",  
this.GetType().Name,  
types.Count()  
));  
foreach (var voidType in types)  
{  
if (!HighLogic.LoadedSceneIsEditor &&  
typeof(IVOID_EditorModule).IsAssignableFrom(voidType))  
{  
continue;  
}  
 
Tools.PostDebugMessage(string.Format(  
"{0}: found Type {1}",  
this.GetType().Name,  
voidType.Name  
));  
 
this.LoadModule(voidType);  
}  
 
this._modulesLoaded = true;  
 
Tools.PostDebugMessage(string.Format(  
"{0}: Loaded {1} modules.",  
this.GetType().Name,  
this.Modules.Count  
));  
}  
 
protected void LoadModule(Type T)  
{  
var existingModules = this._modules.Where(mod => mod.GetType().Name == T.Name);  
if (existingModules.Any())  
{  
Tools.PostDebugMessage(string.Format(  
"{0}: refusing to load {1}: already loaded",  
this.GetType().Name,  
T.Name  
));  
return;  
}  
IVOID_Module module = Activator.CreateInstance(T) as IVOID_Module;  
module.LoadConfig();  
this._modules.Add(module);  
 
Tools.PostDebugMessage(string.Format(  
"{0}: loaded module {1}.",  
this.GetType().Name,  
T.Name  
));  
}  
 
protected void LoadSkins()  
{  
Tools.PostDebugMessage("AssetBase has skins: \n" +  
string.Join("\n\t",  
Resources.FindObjectsOfTypeAll(typeof(GUISkin))  
.Select(s => s.ToString())  
.ToArray()  
)  
);  
 
this.validSkins = Resources.FindObjectsOfTypeAll(typeof(GUISkin))  
.Where(s => !this.forbiddenSkins.Contains(s.name))  
.Select(s => s as GUISkin)  
.GroupBy(s => s.name)  
.Select(g => g.First())  
.ToDictionary(s => s.name);  
 
Tools.PostDebugMessage(string.Format(  
"{0}: loaded {1} GUISkins.",  
this.GetType().Name,  
this.validSkins.Count  
));  
 
this.skinNames = this.validSkins.Keys.ToArray();  
Array.Sort(this.skinNames);  
 
int defaultIdx = int.MinValue;  
 
for (int i = 0; i < this.skinNames.Length; i++)  
{  
if (this.skinNames[i] == this._skinName)  
{  
this._skinIdx = i;  
}  
if (this.skinNames[i] == this.defaultSkin)  
{  
defaultIdx = i;  
}  
if (this._skinIdx != int.MinValue && defaultIdx != int.MinValue)  
{  
break;  
}  
}  
 
if (this._skinIdx == int.MinValue)  
{  
this._skinIdx = defaultIdx;  
}  
 
Tools.PostDebugMessage(string.Format(  
"{0}: _skinIdx = {1}.",  
this.GetType().Name,  
this._skinName.ToString()  
));  
 
this.skinsLoaded = true;  
}  
 
protected void LoadGUIStyles()  
{  
this.LabelStyles["link"] = new GUIStyle(GUI.skin.label);  
this.LabelStyles["link"].fontStyle = FontStyle.Bold;  
 
this.LabelStyles["center"] = new GUIStyle(GUI.skin.label);  
this.LabelStyles["center"].normal.textColor = Color.white;  
this.LabelStyles["center"].alignment = TextAnchor.UpperCenter;  
 
this.LabelStyles["center_bold"] = new GUIStyle(GUI.skin.label);  
this.LabelStyles["center_bold"].normal.textColor = Color.white;  
this.LabelStyles["center_bold"].alignment = TextAnchor.UpperCenter;  
this.LabelStyles["center_bold"].fontStyle = FontStyle.Bold;  
 
this.LabelStyles["right"] = new GUIStyle(GUI.skin.label);  
this.LabelStyles["right"].normal.textColor = Color.white;  
this.LabelStyles["right"].alignment = TextAnchor.UpperRight;  
 
this.LabelStyles["red"] = new GUIStyle(GUI.skin.label);  
this.LabelStyles["red"].normal.textColor = Color.red;  
this.LabelStyles["red"].alignment = TextAnchor.MiddleCenter;  
 
this.iconStyle = new GUIStyle(GUI.skin.button);  
this.iconStyle.padding = new RectOffset(0, 0, 0, 0);  
// this.iconStyle.margin = new RectOffset(0, 0, 0, 0);  
// this.iconStyle.contentOffset = new Vector2(0, 0);  
this.iconStyle.overflow = new RectOffset(0, 0, 0, 0);  
// this.iconStyle.border = new RectOffset(0, 0, 0, 0);  
 
this.GUIStylesLoaded = true;  
}  
 
protected void LoadVesselTypes()  
{  
this._allVesselTypes = Enum.GetValues(typeof(VesselType)).OfType<VesselType>().ToList();  
this.vesselTypesLoaded = true;  
}  
 
protected void LoadBeforeUpdate()  
{  
if (!this.vesselTypesLoaded)  
{  
this.LoadVesselTypes();  
}  
}  
 
protected void InitializeToolbarButton()  
{  
// Do nothing if the Toolbar is not available.  
if (!ToolbarManager.ToolbarAvailable)  
{  
return;  
}  
 
this.ToolbarButton = ToolbarManager.Instance.add(this.VoidName, "coreToggle");  
this.ToolbarButton.Text = this.VoidName;  
this.SetIconTexture(this.powerState | this.activeState);  
 
this.ToolbarButton.Visibility = new GameScenesVisibility(GameScenes.EDITOR, GameScenes.FLIGHT, GameScenes.SPH);  
 
this.ToolbarButton.OnClick +=  
(e) =>  
{  
this.ToggleMainWindow();  
};  
 
Tools.PostDebugMessage(string.Format("{0}: Toolbar Button initialized.", this.GetType().Name));  
}  
 
protected void ToggleMainWindow()  
{  
this.mainGuiMinimized = !this.mainGuiMinimized;  
this.SetIconTexture(this.powerState | this.activeState);  
}  
 
protected void SetIconTexture(IconState state)  
{  
switch (state)  
{  
case (IconState.PowerOff | IconState.Inactive):  
this.SetIconTexture(this.VOIDIconOffInactivePath);  
break;  
case (IconState.PowerOff | IconState.Active):  
this.SetIconTexture(this.VOIDIconOffActivePath);  
break;  
case (IconState.PowerOn | IconState.Inactive):  
this.SetIconTexture(this.VOIDIconOnInactivePath);  
break;  
case (IconState.PowerOn | IconState.Active):  
this.SetIconTexture(this.VOIDIconOnActivePath);  
break;  
default:  
throw new NotImplementedException();  
}  
}  
 
protected void SetIconTexture(string texturePath)  
{  
if (this.ToolbarButton != null)  
{  
this.ToolbarButton.TexturePath = texturePath;  
}  
 
this.VOIDIconTexture = GameDatabase.Instance.GetTexture(texturePath, false);  
}  
 
protected void CheckAndSave()  
{  
this.saveTimer += Time.deltaTime;  
 
if (this.saveTimer > 2f)  
{  
if (!this.configDirty)  
{  
return;  
}  
 
Tools.PostDebugMessage(string.Format(  
"{0}: Time to save, checking if configDirty: {1}",  
this.GetType().Name,  
this.configDirty  
));  
 
this.SaveConfig();  
this.saveTimer = 0;  
}  
}  
 
public override void LoadConfig()  
{  
base.LoadConfig();  
 
foreach (IVOID_Module module in this.Modules)  
{  
module.LoadConfig();  
}  
}  
 
public void SaveConfig()  
{  
var config = KSP.IO.PluginConfiguration.CreateForType<VOID_Core>();  
config.load();  
 
this._SaveToConfig(config);  
 
foreach (IVOID_Module module in this.Modules)  
{  
module._SaveToConfig(config);  
}  
 
config.save();  
 
this.configDirty = false;  
}  
 
protected VOID_Core()  
{  
this._Name = "VOID Core";  
 
System.Version version = this.GetType().Assembly.GetName().Version;  
 
this.VoidVersion = string.Format("{0}.{1}.{2}", version.Major, version.Minor, version.MajorRevision);  
 
this._Active.value = true;  
 
this._skinName = this.defaultSkin;  
this._skinIdx = int.MinValue;  
 
this.VOIDIconOnInactivePath = "VOID/Textures/void_icon_light_glow";  
this.VOIDIconOnActivePath = "VOID/Textures/void_icon_dark_glow";  
this.VOIDIconOffInactivePath = "VOID/Textures/void_icon_light";  
this.VOIDIconOffActivePath = "VOID/Textures/void_icon_dark";  
 
this.vesselSimActive = true;  
 
this.UseToolbarManager = false;  
 
this.LoadConfig();  
 
this.SetIconTexture(this.powerState | this.activeState);  
}  
 
protected enum IconState  
{  
PowerOff = 1,  
PowerOn = 2,  
Inactive = 4,  
Active = 8  
}  
}  
 
public static partial class VOID_Data  
{  
public static VOID_Core core  
{  
get  
{  
return VOID_Core.Instance;  
}  
}  
 
public static double KerbinGee  
{  
get  
{  
return core.Kerbin.gravParameter / (core.Kerbin.Radius * core.Kerbin.Radius);  
}  
}  
}  
}  
 
 
file:b/VOID_Data.cs (new)
  // VOID
  //
  // VOID_Data.cs
  //
  // Copyright © 2014, toadicus
  // All rights reserved.
  //
  // Redistribution and use in source and binary forms, with or without modification,
  // are permitted provided that the following conditions are met:
  //
  // 1. Redistributions of source code must retain the above copyright notice,
  // this list of conditions and the following disclaimer.
  //
  // 2. Redistributions in binary form must reproduce the above copyright notice,
  // this list of conditions and the following disclaimer in the documentation and/or other
  // materials provided with the distribution.
  //
  // 3. Neither the name of the copyright holder nor the names of its contributors may be used
  // to endorse or promote products derived from this software without specific prior written permission.
  //
  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
  using KerbalEngineer.VesselSimulator;
  using KSP;
  using System;
  using System.Collections.Generic;
  using ToadicusTools;
  using UnityEngine;
 
  namespace VOID
  {
  public static class VOID_Data
  {
  private static Dictionary<int, IVOID_DataValue> dataValues = new Dictionary<int, IVOID_DataValue>();
 
  public static Dictionary<int, IVOID_DataValue> DataValues
  {
  get
  {
  return dataValues;
  }
  }
 
  #region Constants
 
  private static double kerbinGee;
 
  public static double KerbinGee
  {
  get
  {
  if (kerbinGee == default(double))
  {
  kerbinGee = Core.HomeBody.gravParameter / (Core.HomeBody.Radius * Core.HomeBody.Radius);
  }
 
  return kerbinGee;
  }
  }
 
  #endregion
 
  #region Core Data
 
  public static VOIDCore Core
  {
  get
  {
  if (!CoreInitialized)
  {
  return null;
  }
 
  switch (HighLogic.LoadedScene)
  {
  case GameScenes.EDITOR:
  return (VOIDCore)VOIDCore_Editor.Instance;
  case GameScenes.FLIGHT:
  return (VOIDCore)VOIDCore_Flight.Instance;
  case GameScenes.SPACECENTER:
  return (VOIDCore)VOIDCore_SpaceCentre.Instance;
  default:
  return null;
  }
  }
  }
 
  public static bool CoreInitialized
  {
  get
  {
  switch (HighLogic.LoadedScene)
  {
  case GameScenes.EDITOR:
  return VOIDCore_Editor.Initialized;
  case GameScenes.FLIGHT:
  return VOIDCore_Flight.Initialized;
  case GameScenes.SPACECENTER:
  return VOIDCore_SpaceCentre.Initialized;
  default:
  return false;
  }
  }
  }
 
  #endregion
 
  #region Atmosphere
 
  public static readonly VOID_DoubleValue atmDensity =
  new VOID_DoubleValue(
  "Atmosphere Density",
  new Func<double>(() => Core.Vessel.atmDensity * 1000f),
  "g/m³"
  );
 
  public static readonly VOID_FloatValue atmLimit =
  new VOID_FloatValue(
  "Atmosphere Limit",
  new Func<float>(() => Core.Vessel.mainBody.maxAtmosphereAltitude),
  "m"
  );
 
  public static readonly VOID_DoubleValue atmPressure =
  new VOID_DoubleValue(
  "Pressure",
  new Func<double>(() => Core.Vessel.staticPressure),
  "atm"
  );
 
  public static readonly VOID_FloatValue temperature =
  new VOID_FloatValue(
  "Temperature",
  new Func<float>(() => Core.Vessel.flightIntegrator.getExternalTemperature()),
  "°C"
  );
 
  #endregion
 
  #region Attitude
 
  public static readonly VOID_StrValue vesselHeading =
  new VOID_StrValue(
  "Heading",
  delegate()
  {
  double heading = Core.Vessel.getSurfaceHeading();
  string cardinal = VOID_Tools.get_heading_text(heading);
 
  return string.Format(
  "{0}° {1}",
  heading.ToString("F2"),
  cardinal
  );
  }
  );
 
  public static readonly VOID_DoubleValue vesselPitch =
  new VOID_DoubleValue(
  "Pitch",
  () => Core.Vessel.getSurfacePitch(),
  "°"
  );
 
  #endregion
 
  #region Career
 
  public static readonly VOID_StrValue fundingStatus =
  new VOID_StrValue(
  string.Intern("Funds"),
  delegate()
  {
  if (VOID_CareerStatus.Instance == null)
  {
  return string.Empty;
  }
 
  return string.Format("{0} ({1})",
  VOID_CareerStatus.Instance.currentFunds.ToString("#,#.##"),
  VOID_CareerStatus.formatDelta(VOID_CareerStatus.Instance.lastFundsChange)
  );
  }
  );
 
  public static readonly VOID_StrValue reputationStatus =
  new VOID_StrValue(
  string.Intern("Reputation"),
  delegate()
  {
  if (VOID_CareerStatus.Instance == null)
  {
  return string.Empty;
  }
 
  return string.Format("{0} ({1})",
  VOID_CareerStatus.Instance.currentReputation.ToString("#,#.##"),
  VOID_CareerStatus.formatDelta(VOID_CareerStatus.Instance.lastRepChange)
  );
  }
  );
 
  public static readonly VOID_StrValue scienceStatus =
  new VOID_StrValue(
  string.Intern("Science"),
  delegate()
  {
  if (VOID_CareerStatus.Instance == null)
  {
  return string.Empty;
  }
 
  return string.Format("{0} ({1})",
  VOID_CareerStatus.Instance.currentScience.ToString("#,#.##"),
  VOID_CareerStatus.formatDelta(VOID_CareerStatus.Instance.lastScienceChange)
  );
  }
  );
 
  #endregion
 
  #region Control
 
  public static readonly VOID_FloatValue mainThrottle =
  new VOID_FloatValue(
  "Throttle",
  new Func<float>(() => Core.Vessel.ctrlState.mainThrottle * 100f),
  "%"
  );
 
  #endregion
 
  #region Engineering
 
  public static readonly VOID_IntValue partCount =
  new VOID_IntValue(
  "Parts",
  new Func<int>(() => Core.Vessel.Parts.Count),
  ""
  );
 
  #region Mass
 
  public static readonly VOID_StrValue comboResourceMass =
  new VOID_StrValue(
  "Resource Mass (curr / total)",
  delegate()
  {
  return string.Format("{0} / {1}",
  stageResourceMass.ValueUnitString("F3"),
  resourceMass.ValueUnitString("F3")
  );
  }
  );
 
  public static readonly VOID_DoubleValue resourceMass =
  new VOID_DoubleValue(
  "Resource Mass",
  delegate()
  {
  if (Core.Stages == null || Core.LastStage == null)
  {
  return double.NaN;
  }
 
  return Core.LastStage.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;
  },
  "tons"
  );
 
  public static readonly VOID_DoubleValue totalMass =
  new VOID_DoubleValue(
  "Total Mass",
  delegate()
  {
  if (Core.Stages == null || Core.LastStage == null)
  {
  return double.NaN;
  }
 
  return Core.LastStage.totalMass;
  },
  "tons"
  );
 
  #endregion
 
  #region DeltaV
 
  public static readonly VOID_DoubleValue stageDeltaV =
  new VOID_DoubleValue(
  "DeltaV (Current Stage)",
  delegate()
  {
  if (Core.Stages == null || Core.LastStage == null)
  return double.NaN;
  return Core.LastStage.deltaV;
  },
  "m/s"
  );
 
  public static readonly VOID_DoubleValue totalDeltaV =
  new VOID_DoubleValue(
  "DeltaV (Total)",
  delegate()
  {
  if (Core.Stages == null || Core.LastStage == null)
  return double.NaN;
  return Core.LastStage.totalDeltaV;
  },
  "m/s"
  );
 
  #endregion
 
  #region Propulsion
 
  public static readonly VOID_StrValue currmaxThrustWeight =
  new VOID_StrValue(
  "T:W (curr/max)",
  delegate()
  {
  if (Core.Stages == null || Core.LastStage == null)
  return "N/A";
 
  return string.Format(
  "{0} / {1}",
  (VOID_Data.currThrustWeight.Value).ToString("F2"),
  (VOID_Data.maxThrustWeight.Value).ToString("F2")
  );
  }
  );
 
  public static readonly VOID_StrValue currmaxThrust =
  new VOID_StrValue(
  "Thrust (curr/max)",
  delegate()
  {
  if (Core.Stages == null || Core.LastStage == null)
  return "N/A";
 
  double currThrust = Core.LastStage.actualThrust;
  double maxThrust = Core.LastStage.thrust;
 
  return string.Format(
  "{0} / {1}",
  currThrust.ToString("F1"),
  maxThrust.ToString("F1")
  );
  }
  );
 
  public static readonly VOID_DoubleValue stageMassFlow =
  new VOID_DoubleValue(
  "Stage Mass Flow",
  delegate()
  {
  if (Core.LastStage == null)
  {
  return double.NaN;
  }
 
  return Core.LastStage.MassFlow();
  },
  "Mg/s"
  );
 
  public static readonly VOID_DoubleValue stageNominalThrust =
  new VOID_DoubleValue(
  "Nominal Stage Thrust",
  delegate()
  {
  if (Core.LastStage == null)
  {
  return double.NaN;
  }
 
  return Core.LastStage.NominalThrust();
  },
  "kN"
  );
 
  #endregion
 
  #region Kinetics
 
  public static readonly VOID_DoubleValue currThrustWeight =
  new VOID_DoubleValue(
  "T:W Ratio",
  delegate()
  {
  if (Core.LastStage == null)
  {
  return double.NaN;
  }
 
  return Core.LastStage.actualThrustToWeight;
  },
  ""
  );
 
 
 
  public static readonly VOID_DoubleValue maxThrustWeight =
  new VOID_DoubleValue(
  "T:W Ratio",
  delegate()
  {
  if (Core.LastStage == null)
  {
  return double.NaN;
  }
 
  return Core.LastStage.thrustToWeight;
  },
  ""
  );
 
  public static readonly VOID_DoubleValue nominalThrustWeight =
  new VOID_DoubleValue(
  "Thrust-to-Weight Ratio",
  delegate()
  {
  if (HighLogic.LoadedSceneIsEditor || currThrustWeight.Value == 0d)
  {
  return maxThrustWeight.Value;
  }
 
  return currThrustWeight.Value;
  },
  ""
  );
 
  public static readonly VOID_DoubleValue surfaceThrustWeight =
  new VOID_DoubleValue(
  "Max T:W @ surface",
  delegate()
  {
  if (Core.Stages == null || Core.LastStage == null)
  return double.NaN;
 
  double maxThrust = Core.LastStage.thrust;
  double mass = Core.LastStage.totalMass;
  double gravity = (VOIDCore.Constant_G * Core.Vessel.mainBody.Mass) /
  (Core.Vessel.mainBody.Radius * Core.Vessel.mainBody.Radius);
  double weight = mass * gravity;
 
  return maxThrust / weight;
  },
  ""
  );
 
  public static readonly VOID_Vector3dValue vesselThrustOffset =
  new VOID_Vector3dValue(
  "Thrust Offset",
  delegate()
  {
  if (Core.Vessel == null)
  {
  return Vector3d.zero;
  }
 
  List<PartModule> engineModules = Core.Vessel.getModulesOfType<PartModule>();
 
  Vector3d thrustPos = Vector3d.zero;
  Vector3d thrustDir = Vector3d.zero;
  float thrust = 0;
 
  foreach (PartModule engine in engineModules)
  {
  float moduleThrust = 0;
 
  switch (engine.moduleName)
  {
  case "ModuleEngines":
  case "ModuleEnginesFX":
  break;
  default:
  continue;
  }
 
  if (!engine.isEnabled)
  {
  continue;
  }
 
  CenterOfThrustQuery cotQuery = new CenterOfThrustQuery();
 
  if (engine is ModuleEngines)
  {
  ModuleEngines engineModule = engine as ModuleEngines;
 
  moduleThrust = engineModule.finalThrust;
 
  engineModule.OnCenterOfThrustQuery(cotQuery);
  }
  else // engine is ModuleEnginesFX
  {
  ModuleEnginesFX engineFXModule = engine as ModuleEnginesFX;
 
  moduleThrust = engineFXModule.finalThrust;
 
  engineFXModule.OnCenterOfThrustQuery(cotQuery);
  }
 
  if (moduleThrust != 0d)
  {
  cotQuery.thrust = moduleThrust;
  }
 
  thrustPos += cotQuery.pos * cotQuery.thrust;
  thrustDir += cotQuery.dir * cotQuery.thrust;
  thrust += cotQuery.thrust;
  }
 
  if (thrust != 0)
  {
  thrustPos /= thrust;
  thrustDir /= thrust;
  }
 
  Transform vesselTransform = Core.Vessel.transform;
 
  thrustPos = vesselTransform.InverseTransformPoint(thrustPos);
  thrustDir = vesselTransform.InverseTransformDirection(thrustDir);
 
  Vector3d thrustOffset = VectorTools.PointDistanceToLine(
  thrustPos, thrustDir.normalized, Core.Vessel.findLocalCenterOfMass());
 
  Tools.PostDebugMessage(typeof(VOID_Data), "vesselThrustOffset:\n" +
  "\tthrustPos: {0}\n" +
  "\tthrustDir: {1}\n" +
  "\tthrustOffset: {2}\n" +
  "\tvessel.CoM: {3}",
  thrustPos,
  thrustDir.normalized,
  thrustOffset,
  Core.Vessel.findWorldCenterOfMass()
  );
 
  return thrustOffset;
  },
  "m"
  );
 
  #endregion
 
  #region Air Breathing
 
  public static readonly VOID_StrValue intakeAirStatus =
  new VOID_StrValue(
  "Intake Air (Curr / Req)",
  delegate()
  {
  double currentAmount;
  double currentRequirement;
 
  currentAmount = 0d;
  currentRequirement = 0d;
 
  foreach (Part part in Core.Vessel.Parts)
  {
  if (part.enabled)
  {
  ModuleEngines engineModule;
  ModuleEnginesFX enginesFXModule;
  List<Propellant> propellantList = null;
 
  if (part.tryGetFirstModuleOfType<ModuleEngines>(out engineModule))
  {
  propellantList = engineModule.propellants;
  }
  else if (part.tryGetFirstModuleOfType<ModuleEnginesFX>(out enginesFXModule))
  {
  propellantList = enginesFXModule.propellants;
  }
 
  if (propellantList != null)