Moved VOID_Localization into Tools/.
Moved VOID_Localization into Tools/.

* 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;
  }
  }
  }
 
 
  // 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 toggleActive { get; set; }
  bool guiRunning { get; }
  bool inValidScene { get; }
  bool inValidGame { 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();
  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 List<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 List<CelestialBody> allBodies { get; }
  public abstract List<CelestialBody> sortedBodyList { get; protected set; }
 
  public abstract List<VesselType> allVesselTypes { get; }
 
  public abstract Stage LastStage { get; protected set; }
  public abstract Stage[] Stages { 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 _SaveToConfig(KSP.IO.PluginConfiguration config)
  {
  base._SaveToConfig(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 _SaveToConfig(KSP.IO.PluginConfiguration config)
  {
  base._SaveToConfig(config);
 
  foreach (HUDWindow window in this.Windows)
  {
  string saveName = string.Format("{0}_{1}", this.GetType().Name, window.WindowName);
  config.SetValue(saveName, window.WindowPos);
  }
  }
  }
 
  public class HUDWindow
  {
  public readonly Rect defaultWindowPos;
 
  private Rect _windowPos;
 
  public Action<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;
  private GameScenes[] validScenes;
  private Game.Modes[] validModes;
 
  protected float lastUpdate = 0;
 
  /*
  * Properties
  * */
  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
  );
  }
  }
 
  public virtual bool toggleActive
  {
  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 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 bool inValidScene
  {
  get
  {
  return this.ValidScenes.Contains(HighLogic.LoadedScene);
  }
  }
 
  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 bool inValidGame
  {
  get
  {
  return this.ValidModes.Contains(HighLogic.CurrentGame.Mode);
  }
  }
 
  public virtual string Name
  {
  get;
  protected set;
  }
 
  public virtual Vessel vessel
  {
  get
  {
  return FlightGlobals.ActiveVessel;
  }
  }
 
  /*
  * Methods
  * */
  public virtual void StartGUI()
  {
  if (!this.toggleActive || 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 _SaveToConfig(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.toggleActive = false;
  }
  }
 
  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);
 
  switch (HighLogic.LoadedScene)
  {
  case GameScenes.EDITOR:
  if (cursorInWindow)
  {
  InputLockManager.SetControlLock(
  ControlTypes.EDITOR_ICON_HOVER | ControlTypes.EDITOR_ICON_PICK |
  ControlTypes.EDITOR_PAD_PICK_COPY | ControlTypes.EDITOR_PAD_PICK_COPY,
  this.inputLockName
  );
  EditorLogic.fetch.Lock(false, false, false, this.inputLockName);
  }
  else
  {
  EditorLogic.fetch.Unlock(this.inputLockName);
  }
  break;
  case GameScenes.FLIGHT:
  if (cursorInWindow)
  {
  InputLockManager.SetControlLock(ControlTypes.CAMERACONTROLS, this.inputLockName);
  }
  else if (InputLockManager.GetControlLock(this.inputLockName) != ControlTypes.None)
  {
  InputLockManager.RemoveControlLock(this.inputLockName);
  }
  break;
  case GameScenes.SPACECENTER:
  if (cursorInWindow)
  {
  InputLockManager.SetControlLock(
  ControlTypes.KSC_FACILITIES | ControlTypes.CAMERACONTROLS,
  this.inputLockName
  );
  }
  else if (InputLockManager.GetControlLock(this.inputLockName) != ControlTypes.None)
  {
  InputLockManager.RemoveControlLock(this.inputLockName);
  }
  break;
  }
 
  if (HighLogic.LoadedSceneIsEditor)
  {
  _Pos = Tools.ClampRectToEditorPad(_Pos);
  }
  else
  {
  _Pos = Tools.ClampRectToScreen(_Pos);
  }
 
  if (_Pos != this.WindowPos)
  {
  this.WindowPos = _Pos;
  this.core.configDirty = true;
  }
  }
  }
  }
 
 
  // VOID
  //
  // VOID_SingletonModule.cs
  //
  // Copyright © 2015, toadicus
  // All rights reserved.
  //
  // Redistribution and use in source and binary forms, with or without modification,
  // are permitted provided that the following conditions are met:
  //
  // 1. Redistributions of source code must retain the above copyright notice,
  // this list of conditions and the following disclaimer.
  //
  // 2. Redistributions in binary form must reproduce the above copyright notice,
  // this list of conditions and the following disclaimer in the documentation and/or other
  // materials provided with the distribution.
  //
  // 3. Neither the name of the copyright holder nor the names of its contributors may be used
  // to endorse or promote products derived from this software without specific prior written permission.
  //
  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  using System;
 
  namespace VOID
  {
  public abstract class VOID_SingletonModule<T> : VOIDCore, IVOID_Module
  where T : VOID_Module, new()
  {
  #region Singleton Members
  /*
  * Static Members
  * */
  protected static bool _initialized = false;
 
  public static bool Initialized
  {
  get
  {
  return _initialized;
  }
  }
 
  protected static T _instance;
 
  public static T Instance
  {
  get
  {
  if (_instance == null)
  {
  _instance = new T();
  _initialized = true;
  }
  return _instance;
  }
  }
  #endregion
  }
  }
 
 
  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)
//  
// IVOID_Module.cs  
//  
// Author:  
// toadicus <>  
//  
// Copyright (c) 2013 toadicus  
//  
// This program is free software: you can redistribute it and/or modify  
// it under the terms of the GNU General Public License as published by  
// the Free Software Foundation, either version 3 of the License, or  
// (at your option) any later version.  
//  
// This program is distributed in the hope that it will be useful,  
// but WITHOUT ANY WARRANTY; without even the implied warranty of  
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the  
// GNU General Public License for more details.  
//  
// You should have received a copy of the GNU General Public License  
// along with this program. If not, see <http://www.gnu.org/licenses/>.  
using System;  
 
namespace 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 {}  
}  
 
file:a/IntCollection.cs (deleted)
//  
// IntCollection.cs  
//  
// Author:  
// toadicus <>  
//  
// Copyright (c) 2013 toadicus  
//  
// This program is free software: you can redistribute it and/or modify  
// it under the terms of the GNU General Public License as published by  
// the Free Software Foundation, either version 3 of the License, or  
// (at your option) any later version.  
//  
// This program is distributed in the hope that it will be useful,  
// but WITHOUT ANY WARRANTY; without even the implied warranty of  
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the  
// GNU General Public License for more details.  
//  
// You should have received a copy of the GNU General Public License  
// along with this program. If not, see <http://www.gnu.org/licenses/>.  
using System;  
 
namespace VOID  
{  
public class IntCollection  
{  
public static implicit operator long(IntCollection c)  
{  
return c.collection;  
}  
 
protected long mask;  
 
public long collection { get; protected set; }  
public ushort maxCount { get; protected set; }  
public ushort wordLength { get; protected set; }  
 
public IntCollection (ushort wordLength = 4, long initialCollection = 0)  
{  
this.collection = initialCollection;  
this.wordLength = wordLength;  
this.maxCount = (ushort)((sizeof(long) * 8 - 1) / wordLength);  
this.mask = ((1 << this.wordLength) - 1);  
}  
 
public ushort this[int idx]  
{  
get {  
if (idx < 0) {  
idx += this.maxCount;  
}  
 
if (idx >= maxCount || idx < 0) {  
throw new IndexOutOfRangeException ();  
}  
 
idx *= wordLength;  
 
return (ushort)((this.collection & (this.mask << idx)) >> idx);  
}  
set {  
if (idx < 0) {  
idx += this.maxCount;  
}  
 
if (idx >= maxCount || idx < 0) {  
throw new IndexOutOfRangeException ();  
}  
 
idx *= wordLength;  
 
long packvalue = value & this.mask;  
 
this.collection &= ~(this.mask << idx);  
this.collection |= packvalue << idx;  
}  
}  
}  
}  
 
 
  // VOID
  //
  // AssemblyInfo.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.Reflection;
  using System.Runtime.CompilerServices;
 
  [assembly: KSPAssemblyDependency("ToadicusTools", 0, 0)]
  [assembly: KSPAssemblyDependency("VesselSimulator", 0, 0)]
 
  // Information about this assembly is defined by the following attributes.
  // Change them to the values specific to your project.
  [assembly: AssemblyTitle("VOID")]
  [assembly: AssemblyDescription("A KSP mod that provides at-a-glance information about Vessels, Orbits, and their states.")]
  [assembly: AssemblyCopyright("toadicus")]
  // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
  // The form "{Major}.{Minor}.*" will automatically update the build and revision,
  // and "{Major}.{Minor}.{Build}.*" will update just the revision.
  [assembly: AssemblyVersion("0.16.4.*")]
  // The following attributes are used to specify the signing key for the assembly,
  // if desired. See the Mono documentation for more information about signing.
  //[assembly: AssemblyDelaySign(false)]
  //[assembly: AssemblyKeyFile("")]
 
 
file:a/Tools.cs (deleted)
//  
// Tools.cs  
//  
// Author:  
// toadicus  
//  
// Copyright (c) 2013 toadicus  
//  
// This program is free software: you can redistribute it and/or modify  
// it under the terms of the GNU General Public License as published by  
// the Free Software Foundation, either version 3 of the License, or  
// (at your option) any later version.  
//  
// This program is distributed in the hope that it will be useful,  
// but WITHOUT ANY WARRANTY; without even the implied warranty of  
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the  
// GNU General Public License for more details.  
//  
// You should have received a copy of the GNU General Public License  
// along with this program. If not, see <http://www.gnu.org/licenses/>.  
//  
// This software uses VesselSimulator and Engineer.Extensions from Engineer Redux.  
// Engineer Redux (c) 2013 cybutek  
// Used by permission.  
//  
///////////////////////////////////////////////////////////////////////////////  
 
using System;  
using System.Collections.Generic;  
using UnityEngine;  
 
namespace VOID  
{  
public static class VOIDLabels  
{  
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";  
}  
 
public static class Tools  
{  
// Toadicus edit: Added re-implementation of the CBAttributeMap.GetAtt function that does not fire a debug message to the game screen.  
public static CBAttributeMap.MapAttribute Toadicus_GetAtt(Vessel vessel)  
{  
CBAttributeMap.MapAttribute mapAttribute;  
 
try  
{  
CBAttributeMap 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 CBAttributeMap.MapAttribute();  
mapAttribute.name = "N/A";  
}  
 
return mapAttribute;  
}  
 
public static string GetLongitudeString(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(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);  
}  
 
/*  
* MuMechLib Methods  
* The methods below are adapted from MuMechLib, © 2013-2014 r4m0n  
* The following methods are a derivative work of the code from MuMechLib in the MechJeb project.  
* Used under license.  
* */  
 
// Derived from MechJeb2/VesselState.cs  
public static Quaternion getSurfaceRotation(this Vessel vessel)  
{  
Vector3 CoM;  
 
try  
{  
CoM = vessel.findWorldCenterOfMass();  
}  
catch  
{  
return new Quaternion();  
}  
 
Vector3 bodyPosition = vessel.mainBody.position;  
Vector3 bodyUp = vessel.mainBody.transform.up;  
 
Vector3 surfaceUp = (CoM - vessel.mainBody.position).normalized;  
Vector3 surfaceNorth = Vector3.Exclude(  
surfaceUp,  
(bodyPosition + bodyUp * (float)vessel.mainBody.Radius) - CoM  
).normalized;  
 
Quaternion surfaceRotation = Quaternion.LookRotation(surfaceNorth, surfaceUp);  
 
return Quaternion.Inverse(  
Quaternion.Euler(90, 0, 0) * Quaternion.Inverse(vessel.GetTransform().rotation) * surfaceRotation  
);  
}  
 
// Derived from MechJeb2/VesselState.cs  
public static double getSurfaceHeading(this Vessel vessel)  
{  
return vessel.getSurfaceRotation().eulerAngles.y;  
}  
 
// Derived from MechJeb2/VesselState.cs  
public static double getSurfacePitch(this Vessel vessel)  
{  
Quaternion vesselSurfaceRotation = vessel.getSurfaceRotation();  
 
return (vesselSurfaceRotation.eulerAngles.x > 180f) ?  
(360f - vesselSurfaceRotation.eulerAngles.x) :  
-vesselSurfaceRotation.eulerAngles.x;  
}  
 
// Derived from MechJeb2/MuUtils.cs  
public static string MuMech_ToSI(  
double d, int digits = 3, int MinMagnitude = 0, int MaxMagnitude = int.MaxValue  
)  
{  
float exponent = (float)Math.Log10(Math.Abs(d));  
exponent = Mathf.Clamp(exponent, (float)MinMagnitude, (float)MaxMagnitude);  
 
if (exponent >= 0)  
{  
switch ((int)Math.Floor(exponent))  
{  
case 0:  
case 1:  
case 2:  
return d.ToString("F" + digits);  
case 3:  
case 4:  
case 5:  
return (d / 1e3).ToString("F" + digits) + "k";  
case 6:  
case 7:  
case 8:  
return (d / 1e6).ToString("F" + digits) + "M";  
case 9:  
case 10:  
case 11:  
return (d / 1e9).ToString("F" + digits) + "G";  
case 12:  
case 13:  
case 14:  
return (d / 1e12).ToString("F" + digits) + "T";  
case 15:  
case 16:  
case 17:  
return (d / 1e15).ToString("F" + digits) + "P";  
case 18:  
case 19:  
case 20:  
return (d / 1e18).ToString("F" + digits) + "E";  
case 21:  
case 22:  
case 23:  
return (d / 1e21).ToString("F" + digits) + "Z";  
default:  
return (d / 1e24).ToString("F" + digits) + "Y";  
}  
}  
else if (exponent < 0)  
{  
switch ((int)Math.Floor(exponent))  
{  
case -1:  
case -2:  
case -3:  
return (d * 1e3).ToString("F" + digits) + "m";  
case -4:  
case -5:  
case -6:  
return (d * 1e6).ToString("F" + digits) + "μ";  
case -7:  
case -8:  
case -9:  
return (d * 1e9).ToString("F" + digits) + "n";  
case -10:  
case -11:  
case -12:  
return (d * 1e12).ToString("F" + digits) + "p";  
case -13:  
case -14:  
case -15:  
return (d * 1e15).ToString("F" + digits) + "f";  
case -16:  
case -17:  
case -18:  
return (d * 1e18).ToString("F" + digits) + "a";  
case -19:  
case -20:  
case -21:  
return (d * 1e21).ToString("F" + digits) + "z";  
default:  
return (d * 1e24).ToString("F" + digits) + "y";  
}  
}  
else  
{  
return "0";  
}  
}  
 
/*  
* END MuMecLib METHODS  
* */  
 
public static string ConvertInterval(double seconds)  
{  
string format_1 = "{0:D1}y {1:D1}d {2:D2}h {3:D2}m {4:D2}.{5:D1}s";  
string format_2 = "{0:D1}d {1:D2}h {2:D2}m {3:D2}.{4:D1}s";  
string format_3 = "{0:D2}h {1:D2}m {2:D2}.{3:D1}s";  
 
TimeSpan interval;  
 
try  
{  
interval = TimeSpan.FromSeconds(seconds);  
}  
catch (OverflowException)  
{  
return "NaN";  
}  
 
int years = interval.Days / 365;  
 
string output;  
if (years > 0)  
{  
output = string.Format(format_1,  
years,  
interval.Days - (years * 365), // subtract years * 365 for accurate day count  
interval.Hours,  
interval.Minutes,  
interval.Seconds,  
interval.Milliseconds.ToString().Substring(0, 1));  
}  
else if (interval.Days > 0)  
{  
output = string.Format(format_2,  
interval.Days,  
interval.Hours,  
interval.Minutes,  
interval.Seconds,  
interval.Milliseconds.ToString().Substring(0, 1));  
}  
else  
{  
output = string.Format(format_3,  
interval.Hours,  
interval.Minutes,  
interval.Seconds,  
interval.Milliseconds.ToString().Substring(0, 1));  
}  
return output;  
}  
 
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)  
{  
double T_target = (2 * Math.PI) * Math.Sqrt(Math.Pow((r_target / 1000), 3) / (grav_param / 1000000000));  
double T_transfer = (2 * Math.PI) * Math.Sqrt(Math.Pow((((r_target / 1000) + (r_current / 1000)) / 2), 3) / (grav_param / 1000000000));  
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 * Math.Pow(v, 2) - 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 = (Math.Pow(v, 2) / 2) - (mu / r);  
h = r * v * Math.Sin(angle);  
ee = Math.Sqrt(1 + ((2 * epsilon * Math.Pow(h, 2)) / Math.Pow(mu, 2)));  
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 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);  
}  
 
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 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 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 static void display_transfer_angles_SUN2PLANET(CelestialBody body, Vessel vessel)  
{  
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
GUILayout.Label("Phase angle (curr/trans):");  
GUILayout.Label(  
Tools.mrenigma03_calcphase(vessel, body).ToString("F3") + "° / " + 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(  
(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 = Tools.Younata_DeltaVToGetToOtherBody(  
(vessel.mainBody.referenceBody.gravParameter / 1000000000),  
(vessel.mainBody.orbit.semiMajorAxis / 1000),  
(body.orbit.semiMajorAxis / 1000)  
);  
double dv2 = Tools.Younata_DeltaVToExitSOI(  
(vessel.mainBody.gravParameter / 1000000000),  
(vessel.orbit.semiMajorAxis / 1000),  
(vessel.mainBody.sphereOfInfluence / 1000),  
Math.Abs(dv1)  
);  
 
double trans_ejection_angle = Tools.Younata_TransferBurnPoint(  
(vessel.orbit.semiMajorAxis / 1000),  
dv2,  
(Math.PI / 2.0),  
(vessel.mainBody.gravParameter / 1000000000)  
);  
double curr_ejection_angle = 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 = Tools.Nivvy_CalcTransferPhaseAngle(  
vessel.mainBody.orbit.semiMajorAxis,  
body.orbit.semiMajorAxis,  
vessel.mainBody.referenceBody.gravParameter  
) % 360;  
double curr_phase_angle = 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 = Tools.adjustCurrPhaseAngle(trans_phase_angle, curr_phase_angle);  
double adj_trans_ejection_angle = Tools.adjust_transfer_ejection_angle(trans_ejection_angle, trans_phase_angle);  
double adj_curr_ejection_angle = 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 = Tools.Younata_DeltaVToGetToOtherBody(  
(vessel.mainBody.gravParameter / 1000000000),  
(vessel.orbit.semiMajorAxis / 1000),  
(body.orbit.semiMajorAxis / 1000)  
);  
 
double trans_phase_angle = 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(  
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 = Tools.Younata_DeltaVToGetToOtherBody(  
(vessel.mainBody.referenceBody.gravParameter / 1000000000),  
(vessel.mainBody.orbit.semiMajorAxis / 1000),  
(body.orbit.semiMajorAxis / 1000)  
);  
double dv2 = Tools.Younata_DeltaVToExitSOI(  
(vessel.mainBody.gravParameter / 1000000000),  
(vessel.orbit.semiMajorAxis / 1000),  
(vessel.mainBody.sphereOfInfluence / 1000),  
Math.Abs(dv1)  
);  
double trans_ejection_angle = Tools.Younata_TransferBurnPoint(  
(vessel.orbit.semiMajorAxis / 1000),  
dv2,  
(Math.PI / 2.0),  
(vessel.mainBody.gravParameter / 1000000000)  
);  
 
double curr_phase_angle = 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 = 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 = Tools.Nivvy_CalcTransferPhaseAngle(  
vessel.mainBody.orbit.semiMajorAxis,  
body.orbit.semiMajorAxis,  
vessel.mainBody.referenceBody.gravParameter  
) % 360;  
 
double adj_phase_angle = 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 = Tools.adjust_transfer_ejection_angle(trans_ejection_angle, trans_phase_angle);  
double adj_curr_ejection_angle = 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();  
}  
// This implementation is adapted from FARGUIUtils.ClampToScreen  
public static Rect ClampRectToScreen(Rect window, int xMargin, int yMargin)  
{  
window.x = Mathf.Clamp(window.x, xMargin - window.width, Screen.width - xMargin);  
window.y = Mathf.Clamp(window.y, yMargin - window.height, Screen.height - yMargin);  
 
return window;  
}  
 
public static Rect ClampRectToScreen(Rect window, int Margin)  
{  
return ClampRectToScreen(window, Margin, Margin);  
}  
 
public static Rect ClampRectToScreen(Rect window)  
{  
return ClampRectToScreen(window, 30);  
}  
 
public static Vector2 ClampV2ToScreen(Vector2 vec, uint xMargin, uint yMargin)  
{  
vec.x = Mathf.Clamp(vec.x, xMargin, Screen.width - xMargin);  
vec.y = Mathf.Clamp(vec.y, yMargin, Screen.height - yMargin);  
 
return vec;  
}  
 
public static Vector2 ClampV2ToScreen(Vector2 vec, uint Margin)  
{  
return ClampV2ToScreen(vec, Margin, Margin);  
}  
 
public static Vector2 ClampV2ToScreen(Vector2 vec)  
{  
return ClampV2ToScreen(vec, 15);  
}  
// UNDONE: This seems messy. Can we clean it up?  
public static Rect DockToWindow(Rect icon, Rect window)  
{  
// We can't set the x and y of the center point directly, so build a new vector.  
Vector2 center = new Vector2();  
 
// If we are near the top or bottom of the screen...  
if (window.yMax > Screen.height - icon.height ||  
window.yMin < icon.height)  
{  
// If we are in a corner...  
if (window.xMax > Screen.width - icon.width ||  
window.xMin < icon.width)  
{  
// If it is a top corner, put the icon below the window.  
if (window.yMax < Screen.height / 2)  
{  
center.y = window.yMax + icon.height / 2;  
}  
// If it is a bottom corner, put the icon above the window.  
else  
{  
center.y = window.yMin - icon.height / 2;  
}  
}  
// If we are not in a corner...  
else  
{  
// If we are along the top edge, align the icon's top edge with the top edge of the window  
if (window.yMax > Screen.height / 2)  
{  
center.y = window.yMax - icon.height / 2;  
}  
// If we are along the bottom edge, align the icon's bottom edge with the bottom edge of the window  
else  
{  
center.y = window.yMin + icon.height / 2;  
}  
}  
 
// At the top or bottom, if we are towards the right, put the icon to the right of the window  
if (window.center.x < Screen.width / 2)  
{  
center.x = window.xMin - icon.width / 2;  
}  
// At the top or bottom, if we are towards the left, put the icon to the left of the window  
else  
{  
center.x = window.xMax + icon.width / 2;  
}  
 
}  
// If we are not along the top or bottom of the screen...  
else  
{  
// By default, center the icon above the window  
center.y = window.yMin - icon.height / 2;  
center.x = window.center.x;  
 
// If we are along a side...  
if (window.xMax > Screen.width - icon.width ||  
window.xMin < icon.width)  
{  
// UNDONE: I'm not sure I like the feel of this part.  
// If we are along a side towards the bottom, put the icon below the window  
if (window.center.y > Screen.height / 2)  
{  
center.y = window.yMax + icon.height / 2;  
}  
 
// Along the left side, align the left edge of the icon with the left edge of the window.  
if (window.xMax > Screen.width - icon.width)  
{  
center.x = window.xMax - icon.width / 2;  
}  
// Along the right side, align the right edge of the icon with the right edge of the window.  
else if (window.xMin < icon.width)  
{  
center.x = window.xMin + icon.width / 2;  
}  
}  
}  
 
// Assign the vector to the center of the rect.  
icon.center = center;  
 
// Return the icon's position.  
return icon;  
}  
 
public static ExperimentSituations GetExperimentSituation(this Vessel vessel)  
{  
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 double Radius(this Vessel vessel)  
{  
double radius;  
 
radius = vessel.altitude;  
 
if (vessel.mainBody != null)  
{  
radius += vessel.mainBody.Radius;  
}  
 
return radius;  
}  
 
public static double TryGetLastMass(this Engineer.VesselSimulator.SimManager simManager)  
{  
if (simManager.Stages == null || simManager.Stages.Length <= Staging.lastStage)  
{  
return double.NaN;  
}  
 
return simManager.Stages[Staging.lastStage].totalMass;  
}  
 
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";  
}  
}  
 
private static ScreenMessage debugmsg = new ScreenMessage("", 2f, ScreenMessageStyle.UPPER_RIGHT);  
 
[System.Diagnostics.Conditional("DEBUG")]  
public static void PostDebugMessage(string Msg)  
{  
if (HighLogic.LoadedScene > GameScenes.SPACECENTER)  
{  
debugmsg.message = Msg;  
ScreenMessages.PostScreenMessage(debugmsg, true);  
}  
 
KSPLog.print(Msg);  
}  
}  
}  
  // 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 Tools.MuMech_ToSI(this, digits) + this.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)
  {
  double magnitude;
  double magLimit;
 
  magnitude = Math.Log10(Math.Abs((double)this));
 
  magLimit = Math.Max(Math.Abs(magnitude), 3d) + 3d;
  magLimit = Math.Round(Math.Ceiling(magLimit / 3f)) * 3d;
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label(this.Label + "ⁱ:", GUILayout.ExpandWidth(true));
  GUILayout.FlexibleSpace();
 
  if (magnitude >= 0)
  {
  GUILayout.Label(this.ValueUnitString(3, int.MinValue, (int)magnitude - digits), GUILayout.ExpandWidth(false));
  }
  else
  {
  GUILayout.Label(this.ValueUnitString(3, (int)magnitude + digits, int.MaxValue), GUILayout.ExpandWidth(false));
  }
  GUILayout.EndHorizontal();
 
  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} within magLimit {2}.",
  this.GetType().Name,
  digits,
  magLimit));
 
  if (Event.current.button == 0)
  {
  digits = (digits + 3) % (int)magLimit;
  }
  else if (Event.current.button == 1)
  {
  digits = (digits - 3) % (int)magLimit;
  }
 
  if (digits < 0)
  {
  digits += (int)magLimit;
  }
 
  Tools.PostDebugMessage(string.Format("{0}: Changed digits to {1}." +
  "\n\tNew minMagnitude: {2}, maxMagnitude: {3}" +
  "\n\tMagnitude: {4}",
  this.GetType().Name,
  digits,
  magnitude >= 0 ? int.MinValue : (int)magnitude - 4 + digits,
  magnitude >= 0 ? (int)magnitude - digits : int.MaxValue,
  magnitude
  ));
  }
  }
 
  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
  //
  // 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
 
  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);
  }
  }
  }
 
  /// <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
  {
  if (GameSettings.KERBIN_TIME)
  {
  return 21600d;
  }
  else
  {
  return 86164.1d;
  }
  }
  }
 
  public static double SecondsPerYear
  {
  get
  {
  if (GameSettings.KERBIN_TIME)
  {
  return 9203545d;
  }
  else
  {
  return 31558149d;
  }
  }
  }
 
  public static UnpackedTime FromSeconds(double seconds)
  {
  UnpackedTime time = new UnpackedTime();
 
  time.years = (int)(seconds / SecondsPerYear);
 
  seconds %= SecondsPerYear;
 
  time.days = (int)(seconds / SecondsPerDay);
 
  seconds %= SecondsPerDay;
 
  time.hours = (int)(seconds / SecondsPerHour);
 
  seconds %= SecondsPerHour;
 
  time.minutes = (int)(seconds / SecondsPerMinute);
 
  seconds %= SecondsPerMinute;
 
  time.seconds = seconds;
 
  return time;
  }
 
  public static explicit operator UnpackedTime(double seconds)
  {
  return FromSeconds(seconds);
  }
 
  public static implicit operator double(UnpackedTime time)
  {
  return time.ToSeconds();
  }
 
  public static UnpackedTime operator+ (UnpackedTime lhs, UnpackedTime rhs)
  {
  return FromSeconds(lhs.ToSeconds() + rhs.ToSeconds());
  }
 
  public static UnpackedTime operator- (UnpackedTime lhs, UnpackedTime rhs)
  {
  return FromSeconds(lhs.ToSeconds() - rhs.ToSeconds());
  }
 
  public int years;
  public int days;
  public int hours;
  public int minutes;
  public double seconds;
 
  public double ToSeconds()
  {
  return (double)years * SecondsPerYear +
  (double)days * SecondsPerDay +
  (double)hours * SecondsPerHour +
  (double)minutes * SecondsPerMinute +
  seconds;
  }
 
  public string FormatAsSpan()
  {
  string format_1 = "{0:D1}y {1:D1}d {2:D2}h {3:D2}m {4:00.0}s";
  string format_2 = "{0:D1}d {1:D2}h {2:D2}m {3:00.0}s";
  string format_3 = "{0:D2}h {1:D2}m {2:00.0}s";
  string format_4 = "{0:D2}m {1:00.0}s";
  string format_5 = "{0:00.0}s";
 
  if (this.years > 0)
  {
  return string.Format(format_1, this.years, this.days, this.hours, this.minutes, this.seconds);
  }
  else if (this.days > 0)
  {
  return string.Format(format_2, this.days, this.hours, this.minutes, this.seconds);
  }
  else if (this.hours > 0)
  {
  return string.Format(format_3, this.hours, this.minutes, this.seconds);
  }
  else if (this.minutes > 0)
  {
  return string.Format(format_4, this.minutes, this.seconds);
  }
  else
  {
  return string.Format(format_5, this.seconds);
  }
  }
 
  public string FormatAsDate()
  {
  string format = "Y{0:#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) {}
  }
 
  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;
  }
  }
  }
 
file:b/VOID.csproj (new)
  <?xml version="1.0" encoding="utf-8"?>
  <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
  <Configuration Condition=" '$(Configuration)' == '' ">Debug_win</Configuration>
  <ProductVersion>8.0.30703</ProductVersion>
  <SchemaVersion>2.0</SchemaVersion>
  <ProjectGuid>{45ACC1CC-942C-4A66-BFC7-8BE375938B18}</ProjectGuid>
  <OutputType>Library</OutputType>
  <RootNamespace>VOID</RootNamespace>
  <AssemblyName>VOID</AssemblyName>
  <CodePage>65001</CodePage>
  <UseMSBuildEngine>False</UseMSBuildEngine>
  <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
  <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
  <ReleaseVersion>0.11</ReleaseVersion>
  <SynchReleaseVersion>false</SynchReleaseVersion>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug_win|AnyCPU' ">
  <DebugSymbols>true</DebugSymbols>
  <DebugType>full</DebugType>
  <Optimize>false</Optimize>
  <OutputPath>bin\Debug</OutputPath>
  <DefineConstants>DEBUG; TRACE</DefineConstants>
  <ErrorReport>prompt</ErrorReport>
  <WarningLevel>4</WarningLevel>
  <ConsolePause>false</ConsolePause>
  <CustomCommands>
  <CustomCommands>
  <Command type="AfterBuild" command="xcopy /Y ${TargetFile} ${ProjectDir}\GameData\VOID\Plugins\" />
  </CustomCommands>
  </CustomCommands>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_win|AnyCPU' ">
  <Optimize>false</Optimize>
  <OutputPath>bin\Release</OutputPath>
  <ErrorReport>prompt</ErrorReport>
  <WarningLevel>4</WarningLevel>
  <ConsolePause>false</ConsolePause>
  <DefineConstants>TRACE</DefineConstants>
  <CustomCommands>
  <CustomCommands>
  <Command type="AfterBuild" command="xcopy /Y ${TargetFile} ${ProjectDir}\GameData\VOID\Plugins\" />
  </CustomCommands>
  </CustomCommands>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug_linux|AnyCPU' ">
  <DebugSymbols>true</DebugSymbols>
  <DebugType>full</DebugType>
  <Optimize>false</Optimize>
  <OutputPath>bin\Debug</OutputPath>
  <DefineConstants>DEBUG; TRACE</DefineConstants>
  <ErrorReport>prompt</ErrorReport>
  <WarningLevel>4</WarningLevel>
  <ConsolePause>false</ConsolePause>
  <CustomCommands>
  <CustomCommands>
  <Command type="AfterBuild" command="cp -afv ${TargetFile} ${ProjectDir}/GameData/${ProjectName}/Plugins/" />
  </CustomCommands>
  </CustomCommands>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_linux|AnyCPU' ">
  <Optimize>false</Optimize>
  <OutputPath>bin\Release</OutputPath>
  <DefineConstants>TRACE</DefineConstants>
  <ErrorReport>prompt</ErrorReport>
  <WarningLevel>4</WarningLevel>
  <ConsolePause>false</ConsolePause>
  <CustomCommands>
  <CustomCommands>
  <Command type="AfterBuild" command="cp -afv ${TargetFile} ${ProjectDir}/GameData/${ProjectName}/Plugins/" />
  </CustomCommands>
  </CustomCommands>
  </PropertyGroup>
  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
  <ItemGroup>
  <Compile Include="VOID_HUD.cs" />
  <Compile Include="VOID_Orbital.cs" />
  <Compile Include="VOID_SurfAtmo.cs" />
  <Compile Include="VOID_VesselInfo.cs" />
  <Compile Include="VOID_Transfer.cs" />
  <Compile Include="VOID_CBInfoBrowser.cs" />
  <Compile Include="VOID_Rendezvous.cs" />
  <Compile Include="VOID_VesselRegister.cs" />
  <Compile Include="VOID_DataLogger.cs" />
  <Compile Include="VOID_EditorHUD.cs" />
  <Compile Include="Properties\AssemblyInfo.cs" />
  <Compile Include="VOID_HUDAdvanced.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\VOID_SingletonModule.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" />
  </ItemGroup>
  <ProjectExtensions>
  <MonoDevelop>
  <Properties>
  <Policies>
  <TextStylePolicy FileWidth="120" TabsToSpaces="False" EolMarker="Unix" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/plain" />
  </Policies>
  </Properties>
  </MonoDevelop>
  </ProjectExtensions>
  <ItemGroup>
  <Reference Include="System">
  <HintPath>..\_KSPAssemblies\System.dll</HintPath>
  </Reference>
  <Reference Include="Assembly-CSharp">
  <HintPath>..\_KSPAssemblies\Assembly-CSharp.dll</HintPath>
  </Reference>
  <Reference Include="UnityEngine">
  <HintPath>..\_KSPAssemblies\UnityEngine.dll</HintPath>
  </Reference>
  </ItemGroup>
  <ItemGroup>
  <ProjectReference Include="..\ToadicusTools\ToadicusTools.csproj">
  <Project>{D48A5542-6655-4149-BC27-B27DF0466F1C}</Project>
  <Name>ToadicusTools</Name>
  </ProjectReference>
  <ProjectReference Include="..\VesselSimulator\VesselSimulator.csproj">
  <Project>{30FD6C0B-D36E-462F-B0FF-F0FAC9C666CF}</Project>
  <Name>VesselSimulator</Name>
  </ProjectReference>
  </ItemGroup>
  <ItemGroup>
  <None Include="GameData\VOID\Textures\ATM_VOID.cfg" />
  </ItemGroup>
  <ItemGroup>
  <Folder Include="API\" />
  <Folder Include="Tools\" />
  <Folder Include="API\Attributes\" />
  </ItemGroup>
  </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_SingletonModule<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;
 
  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;
 
  // Vessel Type Housekeeping
  protected List<VesselType> _allVesselTypes = new List<VesselType>();
  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; }
 
  internal IButton ToolbarButton;
 
  internal ApplicationLauncherButton AppLauncherButton;
 
  /*
  * Properties
  * */
  public override int configVersion
  {
  get
  {
  return this._configVersion;
  }
  }
 
  public bool factoryReset
  {
  get;
  protected set;
  }
 
  public override List<IVOID_Module> Modules
  {
  get
  {
  return this._modules;
  }
  }
 
  public override GUISkin Skin
  {
  get
  {
  if (this.skinsLoaded)
  {
  try
  {
  return this.validSkins[this._skinName];
  }
  catch
  {
  }
  }
 
  return AssetBase.GetGUISkin(this.defaultSkin);
  }
  }
 
  public override int windowID
  {
  get
  {
  if (this._windowID == 0)
  {
  this._windowID = this.windowBaseID;
  }
  return this._windowID++;
  }
  }
 
  public override List<CelestialBody> allBodies
  {
  get
  {
  return FlightGlobals.Bodies;
  }
  }
 
  public override List<CelestialBody> sortedBodyList
  {
  get;
  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 List<VesselType> allVesselTypes
  {
  get
  {
  return this._allVesselTypes;
  }
  }
 
  public override float updateTimer
  {
  get;
  protected set;
  }
 
 
  public override double updatePeriod
  {
  get
  {
  return this._updatePeriod;
  }
  }
 
  public override Stage[] Stages
  {
  get;
  protected set;
  }
 
  public override Stage LastStage
  {
  get;
  protected set;
  }
 
  protected IconState powerState
  {
  get
  {
  if (this.togglePower && this.powerAvailable)
  {
  return IconState.PowerOn;
  }
  else
  {
  return IconState.PowerOff;
  }
 
  }
  }
 
  protected IconState activeState
  {
  get
  {
  if (this.toggleActive)
  {
  return IconState.Inactive;
  }
  else
  {
  return IconState.Active;
  }
 
  }
  }
 
  private bool useToolbarManager;
 
  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;
  }
  }
 
  protected virtual ApplicationLauncher.AppScenes appIconVisibleScenes
  {
  get
  {
  return HighLogic.LoadedScene.ToAppScenes();
  }
  }
 
  /*
  * 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();
  }
 
  if (this.toggleActive)
  {
  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.toggleActive &&
  module.inValidScene &&
  (
  !HighLogic.LoadedSceneIsEditor ||
  (EditorLogic.RootPart != null && EditorLogic.SortedShipList.Count > 0)
  )
  )
  {
  module.StartGUI();
  }
  if (
  module.guiRunning &&
  (
  !module.toggleActive ||
  !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;
  this.SetIconTexture(this.powerState | this.activeState);
  }
  }
 
  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;
  this.SetIconTexture(this.powerState | this.activeState);
  }
  }
 
  if (togglePower || !HighLogic.LoadedSceneIsFlight)
  {
  foreach (IVOID_Module module in this.Modules)
  {
  if (module is VOID_ConfigWindow)
  {
  continue;
  }
 
  module.toggleActive = GUITools.Toggle(module.toggleActive, module.Name);
  }
  }
  }
  else
  {
  GUILayout.Label("-- POWER LOST --", VOID_Styles.labelRed);
  }
 
  VOID_ConfigWindow.Instance.toggleActive = GUITools.Toggle(
  VOID_ConfigWindow.Instance.toggleActive,
  "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");
 
  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
  );
 
  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
  ));
  }
  }
 
  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>().ToList();
  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.toggleActive = !this.toggleActive;
  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.Replace("icon", "appIcon"), false);
 
  if (this.AppLauncherButton != null)
  {
  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();
  }
  }
 
  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._SaveToConfig(config);
 
  foreach (IVOID_Module module in this.Modules)
  {
  module._SaveToConfig(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.toggleActive = 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.SetIconTexture(this.powerState | this.activeState);
 
  this.factoryReset = false;
  }
 
  public virtual 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;
  }
 
  protected enum IconState
  {
  PowerOff = 1,
  PowerOn = 2,
  Inactive = 4,
  Active = 8
  }
  }
  }
 
 
  // 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 - Vessel Orbital Information Display for Kerbal Space Program  
// Copyright (C) 2012 Iannic-ann-od  
// Copyright (C) 2013 Toadicus  
//  
// This program is free software: you can redistribute it and/or modify  
// it under the terms of the GNU General Public License as published by  
// the Free Software Foundation, either version 3 of the License, or  
// (at your option) any later version.  
//  
// This program is distributed in the hope that it will be useful,  
// but WITHOUT ANY WARRANTY; without even the implied warranty of  
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the  
// GNU General Public License for more details.  
//  
// You should have received a copy of the GNU General Public License  
// along with this program. If not, see <http://www.gnu.org/licenses/>.  
//  
///////////////////////////////////////////////////////////////////////////////  
//  
// 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;  
 
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 ();  
SimManager.HardReset();  
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 - Vessel Orbital Information Display for Kerbal Space Program  
// Copyright (C) 2012 Iannic-ann-od  
// Copyright (C) 2013 Toadicus  
//  
// This program is free software: you can redistribute it and/or modify  
// it under the terms of the GNU General Public License as published by  
// the Free Software Foundation, either version 3 of the License, or  
// (at your option) any later version.  
//  
// This program is distributed in the hope that it will be useful,  
// but WITHOUT ANY WARRANTY; without even the implied warranty of  
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the  
// GNU General Public License for more details.  
//  
// You should have received a copy of the GNU General Public License  
// along with this program. If not, see <http://www.gnu.org/licenses/>.  
//  
///////////////////////////////////////////////////////////////////////////////  
//  
// 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;  
 
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 ();  
SimManager.HardReset();  
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_Orbital.cs //
// // VOID_CBInfoBrowser.cs
// Author: //
// toadicus <> // Copyright © 2014, toadicus
// // All rights reserved.
// Copyright (c) 2013 toadicus //
// // Redistribution and use in source and binary forms, with or without modification,
// This program is free software: you can redistribute it and/or modify // are permitted provided that the following conditions are met:
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation, either version 3 of the License, or // 1. Redistributions of source code must retain the above copyright notice,
// (at your option) any later version. // this list of conditions and the following disclaimer.
// //
// This program is distributed in the hope that it will be useful, // 2. Redistributions in binary form must reproduce the above copyright notice,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // this list of conditions and the following disclaimer in the documentation and/or other
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // materials provided with the distribution.
// GNU General Public License for more details. //
// // 3. Neither the name of the copyright holder nor the names of its contributors may be used
// You should have received a copy of the GNU General Public License // to endorse or promote products derived from this software without specific prior written permission.
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
  // 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 KSP;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
  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(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(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(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(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(((Math.Pow((body.Radius), 2) * 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 * Math.Pow(body.Radius, 3)) / 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 / (Math.Pow(body.Radius, 3) * (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) / Math.Pow(body.Radius, 2); 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_WindowModule
  {
  public static VOID_CareerStatus Instance
  {
  get;
  private set;
  }
 
  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()
  {
  if (this.inValidGame && this.inValidScene)
  {
  VOID_CareerStatus.Instance = this;
  }
 
  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;
  }
 
  ~VOID_CareerStatus()
  {
  GameEvents.OnFundsChanged.Remove(this.onFundsChange);
  GameEvents.OnReputationChanged.Remove(this.onRepChange);
  GameEvents.OnScienceChanged.Remove(this.onScienceChange);
  GameEvents.onGameStateLoad.Remove(this.onGameStateLoad);
 
  VOID_CareerStatus.Instance = null;
  }
  }
  }
 
 
  // 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_WindowModule
  {
  public static VOID_ConfigWindow Instance
  {
  get;
  private set;
  }
 
  public override bool inValidScene
  {
  get
  {
  return true;
  }
  }
 
  public override bool inValidGame
  {
  get
  {
  return true;
  }
  }
 
  public VOID_ConfigWindow() : base()
  {
  VOID_ConfigWindow.Instance = this;
 
  this.Name = "VOID Configuration";
  }
 
  public override void ModuleWindow(int id)
  {
  GUILayout.BeginVertical();
 
  this.core.DrawConfigurables();
 
  GUILayout.EndVertical();
  GUI.DragWindow();
  }
 
  ~VOID_ConfigWindow()
  {
  VOID_ConfigWindow.Instance = null;
  }
  }
  }
 
file:a/VOID_Core.cs (deleted)
//  
// VOID_Core.cs  
//  
// Author:  
// toadicus <>  
//  
// Copyright (c) 2013 toadicus  
//  
// This program is free software: you can redistribute it and/or modify  
// it under the terms of the GNU General Public License as published by  
// the Free Software Foundation, either version 3 of the License, or  
// (at your option) any later version.  
//  
// This program is distributed in the hope that it will be useful,  
// but WITHOUT ANY WARRANTY; without even the implied warranty of  
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the  
// GNU General Public License for more details.  
//  
// You should have received a copy of the GNU General Public License  
// along with this program. If not, see <http://www.gnu.org/licenses/>.  
using System;  
using System.Collections.Generic;  
using System.Linq;  
using KSP;  
using UnityEngine;  
using Engineer.VesselSimulator;  
 
namespace VOID  
{  
public class VOID_Core : VOID_Module, IVOID_Module  
{  
/*  
* 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;  
}  
 
public static double Constant_G = 6.674e-11;  
/*  
* Fields  
* */  
protected string VoidName = "VOID";  
protected string VoidVersion = "0.9.20";  
 
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;  
 
// 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 Dictionary<string, GUISkin> skin_list;  
protected List<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 || this._skinName == null)  
{  
return AssetBase.GetGUISkin(this.defaultSkin);  
}  
return this.skin_list[this._skinName];  
}  
}  
 
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;  
}  
set  
{  
if (this._UseToolbarManager == value)  
{  
return;  
}  
 
if (value == false && this.ToolbarButton != null)  
{  
this.ToolbarButton.Destroy();  
this.ToolbarButton = null;  
}  
if (value == true && this.ToolbarButton == null)  
{  
this.InitializeToolbarButton();  
}  
 
this.SetIconTexture(this.powerState | this.activeState);  
 
_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)  
{  
SimManager.Instance.Gravity = VOID_Core.Instance.vessel.mainBody.gravParameter /  
Math.Pow(VOID_Core.Instance.vessel.Radius(), 2);  
SimManager.Instance.TryStartSimulation();  
}  
 
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()  
{  
int skinIdx;  
 
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");  
 
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
 
GUILayout.Label("Skin:", GUILayout.ExpandWidth(false));  
 
_content = new GUIContent();  
 
if (skinNames.Contains(this._skinName))  
{  
skinIdx = skinNames.IndexOf(this._skinName);  
}  
else if (skinNames.Contains(this.defaultSkin))  
{  
skinIdx = skinNames.IndexOf(this.defaultSkin);  
}  
else  
{  
skinIdx = 0;  
}  
 
_content.text = "◄";  
_content.tooltip = "Select previous skin";  
if (GUILayout.Button(_content, GUILayout.ExpandWidth(true)))  
{  
this.GUIStylesLoaded = false;  
skinIdx--;  
if (skinIdx < 0)  
skinIdx = skinNames.Count - 1;  
Tools.PostDebugMessage(string.Format(  
"{0}: new this._skinIdx = {1} :: skin_list.Count = {2}",  
this.GetType().Name,  
this._skinName,  
this.skin_list.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;  
skinIdx++;  
if (skinIdx >= skinNames.Count)  
skinIdx = 0;  
Tools.PostDebugMessage(string.Format(  
"{0}: new this._skinIdx = {1} :: skin_list.Count = {2}",  
this.GetType().Name,  
this._skinName,  
this.skin_list.Count  
));  
}  
 
if (this._skinName != skinNames[skinIdx])  
{  
this._skinName = skinNames[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.skin_list = 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.skin_list.Count  
));  
 
this.skinNames = this.skin_list.Keys.ToList();  
this.skinNames.Sort();  
 
if (this._skinName == null || !this.skinNames.Contains(this._skinName))  
{  
this._skinName = this.defaultSkin;  
Tools.PostDebugMessage(string.Format(  
"{0}: resetting _skinIdx to default.",  
this.GetType().Name  
));  
}  
 
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)