Version 0.9.20 0.9.20
Version 0.9.20

// //
// ToolbarWrapper.cs // ToolbarWrapper.cs
// //
// Author: // Author:
// toadicus <> // toadicus <>
// //
// Copyright (c) 2013 toadicus // Copyright (c) 2013 toadicus
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
using KSP;  
using System; using System;
using System.Linq; using System.Linq;
using System.Linq.Expressions;  
using System.Reflection; using System.Reflection;
using UnityEngine; using UnityEngine;
   
namespace VOID namespace VOID
{ {
  /// <summary>
  /// Wraps a Toolbar clickable button, after fetching it from a foreign assembly.
  /// </summary>
internal class ToolbarButtonWrapper internal class ToolbarButtonWrapper
{ {
protected System.Type ToolbarManager; protected static System.Type ToolbarManager;
protected object TBManagerInstance; protected static object TBManagerInstance;
protected MethodInfo TBManagerAdd; protected static MethodInfo TBManagerAdd;
   
  /// <summary>
  /// Wraps the ToolbarManager class, if present.
  /// </summary>
  /// <returns><c>true</c>, if ToolbarManager is wrapped, <c>false</c> otherwise.</returns>
  protected static bool TryWrapToolbarManager()
  {
  if (ToolbarManager == null)
  {
  Tools.PostDebugMessage(string.Format(
  "{0}: Loading ToolbarManager.",
  "ToolbarButtonWrapper"
  ));
   
  ToolbarManager = AssemblyLoader.loadedAssemblies
  .Select(a => a.assembly.GetExportedTypes())
  .SelectMany(t => t)
  .FirstOrDefault(t => t.FullName == "Toolbar.ToolbarManager");
   
  Tools.PostDebugMessage(string.Format(
  "{0}: Loaded ToolbarManager. Getting Instance.",
  "ToolbarButtonWrapper"
  ));
   
  if (ToolbarManager == null)
  {
  return false;
  }
   
  TBManagerInstance = ToolbarManager.GetProperty(
  "Instance",
  System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static
  )
  .GetValue(null, null);
   
  Tools.PostDebugMessage(string.Format(
  "{0}: Got ToolbarManager Instance '{1}'. Getting 'add' method.",
  "ToolbarButtonWrapper",
  TBManagerInstance
  ));
   
  TBManagerAdd = ToolbarManager.GetMethod("add");
   
  Tools.PostDebugMessage(string.Format(
  "{0}: Got ToolbarManager Instance 'add' method. Loading IButton.",
  "ToolbarButtonWrapper"
  ));
  }
   
  return true;
  }
   
  /// <summary>
  /// Gets a value indicating whether <see cref="Toolbar.ToolbarManager"/> is present.
  /// </summary>
  /// <value><c>true</c>, if ToolbarManager is wrapped, <c>false</c> otherwise.</value>
  public static bool ToolbarManagerPresent
  {
  get
  {
  return TryWrapToolbarManager();
  }
  }
   
  /// <summary>
  /// If ToolbarManager is present, initializes a new instance of the <see cref="VOID.ToolbarButtonWrapper"/> class.
  /// </summary>
  /// <param name="ns">Namespace, usually the plugin name.</param>
  /// <param name="id">Identifier, unique per namespace.</param>
  /// <returns>If ToolbarManager is present, a new <see cref="Toolbar.IButton"/> object, <c>null</c> otherwise.</returns>
  public static ToolbarButtonWrapper TryWrapToolbarButton(string ns, string id)
  {
  if (ToolbarManagerPresent)
  {
  object button = TBManagerAdd.Invoke(TBManagerInstance, new object[] { ns, id });
   
  Tools.PostDebugMessage(string.Format(
  "{0}: Added Button '{1}' with ToolbarManager. Getting 'Text' property",
  "ToolbarButtonWrapper",
  button.ToString()
  ));
   
  return new ToolbarButtonWrapper(button);
  }
  else
  {
  return null;
  }
  }
   
protected System.Type IButton; protected System.Type IButton;
protected object Button; protected object Button;
protected PropertyInfo ButtonText; protected PropertyInfo ButtonText;
protected PropertyInfo ButtonTextColor; protected PropertyInfo ButtonTextColor;
protected PropertyInfo ButtonTexturePath; protected PropertyInfo ButtonTexturePath;
  protected PropertyInfo ButtonToolTip;
  protected PropertyInfo ButtonVisible;
  protected PropertyInfo ButtonVisibility;
  protected PropertyInfo ButtonEffectivelyVisible;
  protected PropertyInfo ButtonEnalbed;
  protected PropertyInfo ButtonImportant;
protected EventInfo ButtonOnClick; protected EventInfo ButtonOnClick;
protected System.Type ClickHandlerType; protected EventInfo ButtonOnMouseEnter;
  protected EventInfo ButtonOnMouseLeave;
protected MethodInfo ButtonDestroy; protected MethodInfo ButtonDestroy;
  protected System.Type GameScenesVisibilityType;
   
  /// <summary>
  /// The text displayed on the button. Set to null to hide text.
  /// </summary>
  /// <remarks>
  /// The text can be changed at any time to modify the button's appearance. Note that since this will also
  /// modify the button's size, this feature should be used sparingly, if at all.
  /// </remarks>
  /// <seealso cref="TexturePath"/>
public string Text public string Text
{ {
get get
{ {
return this.ButtonText.GetValue(this.Button, null) as String; return this.ButtonText.GetValue(this.Button, null) as String;
} }
set set
{ {
this.ButtonText.SetValue(this.Button, value, null); this.ButtonText.SetValue(this.Button, value, null);
} }
} }
   
  /// <summary>
  /// The color the button text is displayed with. Defaults to Color.white.
  /// </summary>
  /// <remarks>
  /// The text color can be changed at any time to modify the button's appearance.
  /// </remarks>
public Color TextColor public Color TextColor
{ {
get get
{ {
return (Color)this.ButtonTextColor.GetValue(this.Button, null); return (Color)this.ButtonTextColor.GetValue(this.Button, null);
} }
set set
{ {
this.ButtonTextColor.SetValue(this.Button, value, null); this.ButtonTextColor.SetValue(this.Button, value, null);
} }
} }
   
  /// <summary>
  /// The path of a texture file to display an icon on the button. Set to null to hide icon.
  /// </summary>
  /// <remarks>
  /// <para>
  /// A texture path on a button will have precedence over text. That is, if both text and texture path
  /// have been set on a button, the button will show the texture, not the text.
  /// </para>
  /// <para>
  /// The texture size must not exceed 24x24 pixels.
  /// </para>
  /// <para>
  /// The texture path must be relative to the "GameData" directory, and must not specify a file name suffix.
  /// Valid example: MyAddon/Textures/icon_mybutton
  /// </para>
  /// <para>
  /// The texture path can be changed at any time to modify the button's appearance.
  /// </para>
  /// </remarks>
  /// <seealso cref="Text"/>
public string TexturePath public string TexturePath
{ {
get get
{ {
return this.ButtonTexturePath.GetValue(this.Button, null) as string; return this.ButtonTexturePath.GetValue(this.Button, null) as string;
} }
set set
{ {
this.ButtonTexturePath.SetValue(this.Button, value, null); this.ButtonTexturePath.SetValue(this.Button, value, null);
} }
} }
   
private ToolbarButtonWrapper() {} /// <summary>
  /// The button's tool tip text. Set to null if no tool tip is desired.
public ToolbarButtonWrapper(string ns, string id) /// </summary>
{ /// <remarks>
Tools.PostDebugMessage(string.Format( /// Tool Tip Text Should Always Use Headline Style Like This.
"{0}: Loading ToolbarManager.", /// </remarks>
this.GetType().Name public string ToolTip
)); {
  get
this.ToolbarManager = AssemblyLoader.loadedAssemblies {
.Select(a => a.assembly.GetExportedTypes()) return this.ButtonToolTip.GetValue(this.Button, null) as string;
.SelectMany(t => t) }
.FirstOrDefault(t => t.FullName == "Toolbar.ToolbarManager"); set
  {
Tools.PostDebugMessage(string.Format( this.ButtonToolTip.SetValue(this.Button, value, null);
"{0}: Loaded ToolbarManager. Getting Instance.", }
this.GetType().Name }
));  
  /// <summary>
this.TBManagerInstance = this.ToolbarManager.GetProperty( /// Whether this button is currently visible or not. Can be used in addition to or as a replacement for <see cref="Visibility"/>.
"Instance", /// </summary>
System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static public bool Visible
) {
.GetValue(null, null); get
  {
Tools.PostDebugMessage(string.Format( return (bool)this.ButtonVisible.GetValue(this.Button, null);
"{0}: Got ToolbarManager Instance '{1}'. Getting 'add' method.", }
this.GetType().Name, set
this.TBManagerInstance {
)); this.ButtonVisible.SetValue(this.Button, value, null);
  }
this.TBManagerAdd = this.ToolbarManager.GetMethod("add"); }
   
Tools.PostDebugMessage(string.Format( /// <summary>
"{0}: Got ToolbarManager Instance 'add' method. Loading IButton.", /// Whether this button is currently effectively visible or not. This is a combination of
this.GetType().Name /// <see cref="Visible"/> and <see cref="Visibility"/>.
)); /// </summary>
  /// <remarks>
  /// Note that the toolbar is not visible in certain game scenes, for example the loading screens. This property
  /// does not reflect button invisibility in those scenes.
  /// </remarks>
  public bool EffectivelyVisible
  {
  get
  {
  return (bool)this.ButtonEffectivelyVisible.GetValue(this.Button, null);
  }
  }
   
  /// <summary>
  /// Whether this button is currently enabled (clickable) or not. This will not affect the player's ability to
  /// position the button on their screen.
  /// </summary>
  public bool Enabled
  {
  get
  {
  return (bool)this.ButtonEnalbed.GetValue(this.Button, null);
  }
  set
  {
  this.ButtonEnalbed.SetValue(this.Button, value, null);
  }
  }
   
  /// <summary>
  /// Whether this button is currently "important." Set to false to return to normal button behaviour.
  /// </summary>
  /// <remarks>
  /// <para>
  /// This can be used to temporarily force the button to be shown on the screen regardless of the toolbar being
  /// currently in auto-hidden mode. For example, a button that signals the arrival of a private message in a
  /// chat room could mark itself as "important" as long as the message has not been read.
  /// </para>
  /// <para>
  /// Setting this property does not change the appearance of the button. use <see cref="TexturePath"/> to
  /// change the button's icon.
  /// </para>
  /// <para>
  /// This feature should be used only sparingly, if at all, since it forces the button to be displayed on screen
  /// even when it normally wouldn't.
  /// </para>
  /// </remarks>
  /// <value><c>true</c> if important; otherwise, <c>false</c>.</value>
  public bool Important
  {
  get
  {
  return (bool)this.ButtonImportant.GetValue(this.Button, null);
  }
  set
  {
  this.ButtonImportant.SetValue(this.Button, value, null);
  }
  }
   
  private ToolbarButtonWrapper()
  {
  }
   
  /// <summary>
  /// Initializes a new instance of the <see cref="VOID.ToolbarButtonWrapper"/> class.
  /// </summary>
  /// <param name="ns">Namespace, usually the plugin name.</param>
  /// <param name="id">Identifier, unique per namespace.</param>
  protected ToolbarButtonWrapper(object button)
  {
  this.Button = button;
   
this.IButton = AssemblyLoader.loadedAssemblies this.IButton = AssemblyLoader.loadedAssemblies
.Select(a => a.assembly.GetExportedTypes()) .Select(a => a.assembly.GetExportedTypes())
.SelectMany(t => t) .SelectMany(t => t)
.FirstOrDefault(t => t.FullName == "Toolbar.IButton"); .FirstOrDefault(t => t.FullName == "Toolbar.IButton");
   
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: Loaded IButton. Adding Button with ToolbarManager.", "{0}: Loaded IButton. Adding Button with ToolbarManager.",
this.GetType().Name this.GetType().Name
)); ));
   
this.Button = this.TBManagerAdd.Invoke(this.TBManagerInstance, new object[] {ns, id});  
   
Tools.PostDebugMessage(string.Format(  
"{0}: Added Button '{1}' with ToolbarManager. Getting 'Text' property",  
this.GetType().Name,  
this.Button.ToString()  
));  
   
this.ButtonText = this.IButton.GetProperty("Text"); this.ButtonText = this.IButton.GetProperty("Text");
   
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: Got 'Text' property. Getting 'TextColor' property.", "{0}: Got 'Text' property. Getting 'TextColor' property.",
this.GetType().Name this.GetType().Name
)); ));
   
this.ButtonTextColor = this.IButton.GetProperty("TextColor"); this.ButtonTextColor = this.IButton.GetProperty("TextColor");
   
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: Got 'TextColor' property. Getting 'TexturePath' property.", "{0}: Got 'TextColor' property. Getting 'TexturePath' property.",
this.GetType().Name this.GetType().Name
)); ));
   
this.ButtonTexturePath = this.IButton.GetProperty("TexturePath"); this.ButtonTexturePath = this.IButton.GetProperty("TexturePath");
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: Got 'TexturePath' property. Getting 'OnClick' property.", "{0}: Got 'TexturePath' property. Getting 'ToolTip' property.",
this.GetType().Name this.GetType().Name
)); ));
   
  this.ButtonToolTip = this.IButton.GetProperty("ToolTip");
   
  Tools.PostDebugMessage(string.Format(
  "{0}: Got 'ToolTip' property. Getting 'Visible' property.",
  this.GetType().Name
  ));
   
  this.ButtonVisible = this.IButton.GetProperty("Visible");
   
  Tools.PostDebugMessage(string.Format(
  "{0}: Got 'Visible' property. Getting 'Visibility' property.",
  this.GetType().Name
  ));
   
  this.ButtonVisibility = this.IButton.GetProperty("Visibility");
   
  Tools.PostDebugMessage(string.Format(
  "{0}: Got 'Visibility' property. Getting 'EffectivelyVisible' property.",
  this.GetType().Name
  ));
   
  this.ButtonEffectivelyVisible = this.IButton.GetProperty("EffectivelyVisible");
   
  Tools.PostDebugMessage(string.Format(
  "{0}: Got 'Visibility' property. Getting 'Enabled' property.",
  this.GetType().Name
  ));
   
  this.ButtonEnalbed = this.IButton.GetProperty("Enabled");
   
  Tools.PostDebugMessage(string.Format(
  "{0}: Got 'Enabled' property. Getting 'OnClick' event.",
  this.GetType().Name
  ));
   
  this.ButtonImportant = this.IButton.GetProperty("Important");
   
  Tools.PostDebugMessage(string.Format(
  "{0}: Got 'Enabled' property. Getting 'OnClick' event.",
  this.GetType().Name
  ));
   
this.ButtonOnClick = this.IButton.GetEvent("OnClick"); this.ButtonOnClick = this.IButton.GetEvent("OnClick");
this.ClickHandlerType = this.ButtonOnClick.EventHandlerType;  
  Tools.PostDebugMessage(string.Format(
Tools.PostDebugMessage(string.Format( "{0}: Got 'OnClick' event '{1}'. Getting 'OnMouseEnter' event.",
"{0}: Got 'OnClick' property '{1}'. Getting 'Destroy' method.", this.GetType().Name,
  this.ButtonOnClick.ToString()
  ));
   
  this.ButtonOnMouseEnter = this.IButton.GetEvent("OnMouseEnter");
   
  Tools.PostDebugMessage(string.Format(
  "{0}: Got 'OnMouseEnter' event '{1}'. Getting 'OnMouseLeave' event.",
this.GetType().Name, this.GetType().Name,
this.ButtonOnClick.ToString() this.ButtonOnClick.ToString()
)); ));
   
  this.ButtonOnMouseLeave = this.IButton.GetEvent("OnMouseLeave");
   
  Tools.PostDebugMessage(string.Format(
  "{0}: Got 'OnMouseLeave' event '{1}'. Getting 'Destroy' method.",
  this.GetType().Name,
  this.ButtonOnClick.ToString()
  ));
   
this.ButtonDestroy = this.IButton.GetMethod("Destroy"); this.ButtonDestroy = this.IButton.GetMethod("Destroy");
   
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: Got 'Destroy' property '{1}'.", "{0}: Got 'Destroy' property '{1}'. Loading GameScenesVisibility class.",
this.GetType().Name, this.GetType().Name,
this.ButtonDestroy.ToString() this.ButtonDestroy.ToString()
)); ));
   
  this.GameScenesVisibilityType = AssemblyLoader.loadedAssemblies
  .Select(a => a.assembly.GetExportedTypes())
  .SelectMany(t => t)
  .FirstOrDefault(t => t.FullName == "Toolbar.GameScenesVisibility");
   
  Tools.PostDebugMessage(string.Format(
  "{0}: Got 'GameScenesVisibility' class '{1}'.",
  this.GetType().Name,
  this.GameScenesVisibilityType.ToString()
  ));
   
Tools.PostDebugMessage("ToolbarButtonWrapper built!"); Tools.PostDebugMessage("ToolbarButtonWrapper built!");
} }
   
  /// <summary>
  /// Adds event handler to receive "on click" events.
  /// </summary>
  /// <example>
  /// <code>
  /// ToolbarButtonWrapper button = ...
  /// button.AddButtonClickHandler(
  /// (e) =>
  /// {
  /// Debug.Log("button clicked, mouseButton: " + e.Mousebutton");
  /// }
  /// );
  /// </code>
  /// </example>
  /// <param name="Handler">Delegate to handle "on click" events</param>
public void AddButtonClickHandler(Action<object> Handler) public void AddButtonClickHandler(Action<object> Handler)
{ {
Delegate d = Delegate.CreateDelegate(this.ClickHandlerType, Handler.Target, Handler.Method); this.AddButtonEventHandler(this.ButtonOnClick, Handler);
MethodInfo addHandler = this.ButtonOnClick.GetAddMethod(); }
   
  /// <summary>
  /// Adds event handler that can be registered with to receive "on mouse enter" events.
  /// </summary>
  /// <example>
  /// <code>
  /// ToolbarWrapperButton button = ...
  /// button.AddButtonOnMouseEnterHandler(
  /// (e) =>
  /// {
  /// Debug.Log("mouse entered button");
  /// }
  /// );
  /// </code>
  /// </example>
  /// <param name="Handler">Delegate to handle "OnMouseEnter" events.</param>
  public void AddButtonOnMouseEnterHandler(Action<object> Handler)
  {
  this.AddButtonEventHandler(this.ButtonOnMouseEnter, Handler);
  }
   
  /// <summary>
  /// Adds event handler that can be registered with to receive "on mouse leave" events.
  /// </summary>
  /// <example>
  /// <code>
  /// ToolbarWrapperButton button = ...
  /// button.AddButtonOnMouseLeaveHandler(
  /// (e) =>
  /// {
  /// Debug.Log("mouse left button");
  /// }
  /// );
  /// </code>
  /// </example>
  /// <param name="Handler">Delegate to handle "OnMouseLeave" events.</param>
  public void AddButtonOnMouseLeaveHandler(Action<object> Handler)
  {
  this.AddButtonEventHandler(this.ButtonOnMouseLeave, Handler);
  }
   
  /// <summary>
  /// Sets this button's visibility. Can be used in addition to or as a replacement for <see cref="Visible"/>.
  /// </summary>
  /// <param name="gameScenes">Array of GameScene objects in which the button should be visible.</param>
  public void SetButtonVisibility(params GameScenes[] gameScenes)
  {
  object GameScenesVisibilityObj = Activator.CreateInstance(this.GameScenesVisibilityType, gameScenes);
  this.ButtonVisibility.SetValue(this.Button, GameScenesVisibilityObj, null);
  }
   
  /// <summary>
  /// Permanently destroys this button so that it is no longer displayed.
  /// Should be used when a plugin is stopped to remove leftover buttons.
  /// </summary>
  public void Destroy()
  {
  this.ButtonDestroy.Invoke(this.Button, null);
  }
   
  // Utility method for use with the AddButton<event>Handler API methods.
  protected void AddButtonEventHandler(EventInfo Event, Action<object> Handler)
  {
  Delegate d = Delegate.CreateDelegate(Event.EventHandlerType, Handler.Target, Handler.Method);
  MethodInfo addHandler = Event.GetAddMethod();
addHandler.Invoke(this.Button, new object[] { d }); addHandler.Invoke(this.Button, new object[] { d });
}  
   
public void Destroy()  
{  
this.ButtonDestroy.Invoke(this.Button, null);  
} }
} }
} }
   
   
file:a/Tools.cs -> file:b/Tools.cs
// //
// Tools.cs // Tools.cs
// //
// Author: // Author:
// toadicus // toadicus
// //
// Copyright (c) 2013 toadicus // Copyright (c) 2013 toadicus
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
// //
// This software uses VesselSimulator and Engineer.Extensions from Engineer Redux. // This software uses VesselSimulator and Engineer.Extensions from Engineer Redux.
// Engineer Redux (c) 2013 cybutek // Engineer Redux (c) 2013 cybutek
// Used by permission. // Used by permission.
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
   
   
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
   
namespace VOID namespace VOID
{ {
public static class VOIDLabels public static class VOIDLabels
{ {
public static string void_primary = "Primary"; public static string void_primary = "Primary";
public static string void_altitude_asl = "Altitude (ASL)"; public static string void_altitude_asl = "Altitude (ASL)";
public static string void_velocity = "Velocity"; public static string void_velocity = "Velocity";
public static string void_apoapsis = "Apoapsis"; public static string void_apoapsis = "Apoapsis";
public static string void_periapsis = "Periapsis"; public static string void_periapsis = "Periapsis";
} }
   
public static class Tools 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. // 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) public static CBAttributeMap.MapAttribute Toadicus_GetAtt(Vessel vessel)
{ {
CBAttributeMap.MapAttribute mapAttribute; CBAttributeMap.MapAttribute mapAttribute;
   
try try
{ {
CBAttributeMap BiomeMap = vessel.mainBody.BiomeMap; CBAttributeMap BiomeMap = vessel.mainBody.BiomeMap;
   
double lat = vessel.latitude * Math.PI / 180d; double lat = vessel.latitude * Math.PI / 180d;
double lon = vessel.longitude * Math.PI / 180d; double lon = vessel.longitude * Math.PI / 180d;
   
  mapAttribute = BiomeMap.GetAtt(lat, lon);
   
  /*
lon -= Math.PI / 2d; lon -= Math.PI / 2d;
   
if (lon < 0d) if (lon < 0d)
{ {
lon += 2d * Math.PI; lon += 2d * Math.PI;
} }
   
float v = (float)(lat / Math.PI) + 0.5f; float v = (float)(lat / Math.PI) + 0.5f;
float u = (float)(lon / (2d * Math.PI)); float u = (float)(lon / (2d * Math.PI));
   
Color pixelBilinear = BiomeMap.Map.GetPixelBilinear (u, v); Color pixelBilinear = BiomeMap.Map.GetPixelBilinear(u, v);
mapAttribute = BiomeMap.defaultAttribute; mapAttribute = BiomeMap.defaultAttribute;
   
if (BiomeMap.Map != null) if (BiomeMap.Map != null)
{ {
if (BiomeMap.exactSearch) if (BiomeMap.exactSearch)
{ {
for (int i = 0; i < BiomeMap.Attributes.Length; ++i) for (int i = 0; i < BiomeMap.Attributes.Length; ++i)
{ {
if (pixelBilinear == BiomeMap.Attributes[i].mapColor) if (pixelBilinear == BiomeMap.Attributes[i].mapColor)
{ {
mapAttribute = BiomeMap.Attributes[i]; mapAttribute = BiomeMap.Attributes[i];
} }
} }
} }
else else
{ {
float zero = 0; float zero = 0;
float num = 1 / zero; float num = 1 / zero;
for (int j = 0; j < BiomeMap.Attributes.Length; ++j) for (int j = 0; j < BiomeMap.Attributes.Length; ++j)
{ {
Color mapColor = BiomeMap.Attributes [j].mapColor; Color mapColor = BiomeMap.Attributes[j].mapColor;
float sqrMagnitude = ((Vector4)(mapColor - pixelBilinear)).sqrMagnitude; float sqrMagnitude = ((Vector4)(mapColor - pixelBilinear)).sqrMagnitude;
if (sqrMagnitude < num) if (sqrMagnitude < num)
{ {
bool testCase = true; bool testCase = true;
if (BiomeMap.nonExactThreshold != -1) if (BiomeMap.nonExactThreshold != -1)
{ {
testCase = (sqrMagnitude < BiomeMap.nonExactThreshold); testCase = (sqrMagnitude < BiomeMap.nonExactThreshold);
} }
if (testCase) if (testCase)
{ {
mapAttribute = BiomeMap.Attributes[j]; mapAttribute = BiomeMap.Attributes[j];
num = sqrMagnitude; num = sqrMagnitude;
} }
} }
} }
} }
} }
  */
} }
catch (NullReferenceException) catch (NullReferenceException)
{ {
mapAttribute = new CBAttributeMap.MapAttribute(); mapAttribute = new CBAttributeMap.MapAttribute();
mapAttribute.name = "N/A"; mapAttribute.name = "N/A";
} }
   
return mapAttribute; return mapAttribute;
} }
   
public static string GetLongitudeString(Vessel vessel, string format="F4") public static string GetLongitudeString(Vessel vessel, string format = "F4")
{ {
string dir_long = "W"; string dir_long = "W";
double v_long = vessel.longitude; double v_long = vessel.longitude;
   
v_long = FixDegreeDomain(v_long); v_long = FixDegreeDomain(v_long);
   
if (v_long < -180d) if (v_long < -180d)
{ {
v_long += 360d; v_long += 360d;
} }
if (v_long >= 180) if (v_long >= 180)
{ {
v_long -= 360d; v_long -= 360d;
} }
   
if (v_long > 0) dir_long = "E"; if (v_long > 0)
  dir_long = "E";
   
return string.Format("{0}° {1}", Math.Abs(v_long).ToString(format), dir_long); return string.Format("{0}° {1}", Math.Abs(v_long).ToString(format), dir_long);
} }
   
public static string GetLatitudeString(Vessel vessel, string format="F4") public static string GetLatitudeString(Vessel vessel, string format = "F4")
{ {
string dir_lat = "S"; string dir_lat = "S";
double v_lat = vessel.latitude; double v_lat = vessel.latitude;
if (v_lat > 0) dir_lat = "N"; if (v_lat > 0)
  dir_lat = "N";
   
return string.Format("{0}° {1}", Math.Abs(v_lat).ToString(format), dir_lat); return string.Format("{0}° {1}", Math.Abs(v_lat).ToString(format), dir_lat);
} }
   
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
   
//For MuMech_get_heading() //For MuMech_get_heading()
public class MuMech_MovingAverage public class MuMech_MovingAverage
{ {
private double[] store; private double[] store;
private int storeSize; private int storeSize;
private int nextIndex = 0; private int nextIndex = 0;
   
public double value public double value
{ {
get get
{ {
double tmp = 0; double tmp = 0;
foreach (double i in store) foreach (double i in store)
{ {
tmp += i; tmp += i;
} }
return tmp / storeSize; return tmp / storeSize;
} }
set set
{ {
store[nextIndex] = value; store[nextIndex] = value;
nextIndex = (nextIndex + 1) % storeSize; nextIndex = (nextIndex + 1) % storeSize;
} }
} }
   
public MuMech_MovingAverage(int size = 10, double startingValue = 0) public MuMech_MovingAverage(int size = 10, double startingValue = 0)
{ {
storeSize = size; storeSize = size;
store = new double[size]; store = new double[size];
force(startingValue); force(startingValue);
} }
   
public void force(double newValue) public void force(double newValue)
{ {
for (int i = 0; i < storeSize; i++) for (int i = 0; i < storeSize; i++)
{ {
store[i] = newValue; store[i] = newValue;
} }
} }
   
public static implicit operator double(MuMech_MovingAverage v) public static implicit operator double(MuMech_MovingAverage v)
{ {
return v.value; return v.value;
} }
   
public override string ToString() public override string ToString()
{ {
return value.ToString(); return value.ToString();
} }
   
public string ToString(string format) public string ToString(string format)
{ {
return value.ToString(format); return value.ToString(format);
} }
} }
   
//From http://svn.mumech.com/KSP/trunk/MuMechLib/VOID.vesselState.cs //From http://svn.mumech.com/KSP/trunk/MuMechLib/VOID.vesselState.cs
public static double MuMech_get_heading(Vessel vessel) public static double MuMech_get_heading(Vessel vessel)
{ {
Vector3d CoM = vessel.findWorldCenterOfMass(); Vector3d CoM;
   
  try
  {
  CoM = vessel.findWorldCenterOfMass();
  }
  catch
  {
  return double.NaN;
  }
   
Vector3d up = (CoM - vessel.mainBody.position).normalized; Vector3d up = (CoM - vessel.mainBody.position).normalized;
Vector3d north = Vector3d.Exclude( Vector3d north = Vector3d.Exclude(
up, up,
(vessel.mainBody.position + (vessel.mainBody.position +
vessel.mainBody.transform.up * (float)vessel.mainBody.Radius vessel.mainBody.transform.up * (float)vessel.mainBody.Radius
) - CoM).normalized; ) - CoM).normalized;
   
Quaternion rotationSurface = Quaternion.LookRotation(north, up); Quaternion rotationSurface = Quaternion.LookRotation(north, up);
Quaternion rotationvesselSurface = Quaternion.Inverse( Quaternion rotationvesselSurface = Quaternion.Inverse(
Quaternion.Euler(90, 0, 0) * Quaternion.Euler(90, 0, 0) *
Quaternion.Inverse(vessel.transform.rotation) * Quaternion.Inverse(vessel.transform.rotation) *
rotationSurface); rotationSurface);
   
return rotationvesselSurface.eulerAngles.y; return rotationvesselSurface.eulerAngles.y;
} }
   
//From http://svn.mumech.com/KSP/trunk/MuMechLib/MuUtils.cs //From http://svn.mumech.com/KSP/trunk/MuMechLib/MuUtils.cs
public static string MuMech_ToSI( public static string MuMech_ToSI(
double d, int digits = 3, int MinMagnitude = 0, int MaxMagnitude = int.MaxValue double d, int digits = 3, int MinMagnitude = 0, int MaxMagnitude = int.MaxValue
) )
{ {
float exponent = (float)Math.Log10(Math.Abs(d)); float exponent = (float)Math.Log10(Math.Abs(d));
exponent = Mathf.Clamp(exponent, (float)MinMagnitude, (float)MaxMagnitude); exponent = Mathf.Clamp(exponent, (float)MinMagnitude, (float)MaxMagnitude);
   
if (exponent >= 0) if (exponent >= 0)
{ {
switch ((int)Math.Floor(exponent)) switch ((int)Math.Floor(exponent))
{ {
case 0: case 0:
case 1: case 1:
case 2: case 2:
return d.ToString("F" + digits); return d.ToString("F" + digits);
case 3: case 3:
case 4: case 4:
case 5: case 5:
return (d / 1e3).ToString("F" + digits) + "k"; return (d / 1e3).ToString("F" + digits) + "k";
case 6: case 6:
case 7: case 7:
case 8: case 8:
return (d / 1e6).ToString("F" + digits) + "M"; return (d / 1e6).ToString("F" + digits) + "M";
case 9: case 9:
case 10: case 10:
case 11: case 11:
return (d / 1e9).ToString("F" + digits) + "G"; return (d / 1e9).ToString("F" + digits) + "G";
case 12: case 12:
case 13: case 13:
case 14: case 14:
return (d / 1e12).ToString("F" + digits) + "T"; return (d / 1e12).ToString("F" + digits) + "T";
case 15: case 15:
case 16: case 16:
case 17: case 17:
return (d / 1e15).ToString("F" + digits) + "P"; return (d / 1e15).ToString("F" + digits) + "P";
case 18: case 18:
case 19: case 19:
case 20: case 20:
return (d / 1e18).ToString("F" + digits) + "E"; return (d / 1e18).ToString("F" + digits) + "E";
case 21: case 21:
case 22: case 22:
case 23: case 23:
return (d / 1e21).ToString("F" + digits) + "Z"; return (d / 1e21).ToString("F" + digits) + "Z";
default: default:
return (d / 1e24).ToString("F" + digits) + "Y"; return (d / 1e24).ToString("F" + digits) + "Y";
} }
} }
else if (exponent < 0) else if (exponent < 0)
{ {
switch ((int)Math.Floor(exponent)) switch ((int)Math.Floor(exponent))
{ {
case -1: case -1:
case -2: case -2:
case -3: case -3:
return (d * 1e3).ToString("F" + digits) + "m"; return (d * 1e3).ToString("F" + digits) + "m";
case -4: case -4:
case -5: case -5:
case -6: case -6:
return (d * 1e6).ToString("F" + digits) + "μ"; return (d * 1e6).ToString("F" + digits) + "μ";
case -7: case -7:
case -8: case -8:
case -9: case -9:
return (d * 1e9).ToString("F" + digits) + "n"; return (d * 1e9).ToString("F" + digits) + "n";
case -10: case -10:
case -11: case -11:
case -12: case -12:
return (d * 1e12).ToString("F" + digits) + "p"; return (d * 1e12).ToString("F" + digits) + "p";
case -13: case -13:
case -14: case -14:
case -15: case -15:
return (d * 1e15).ToString("F" + digits) + "f"; return (d * 1e15).ToString("F" + digits) + "f";
case -16: case -16:
case -17: case -17:
case -18: case -18:
return (d * 1e18).ToString("F" + digits) + "a"; return (d * 1e18).ToString("F" + digits) + "a";
case -19: case -19:
case -20: case -20:
case -21: case -21:
return (d * 1e21).ToString("F" + digits) + "z"; return (d * 1e21).ToString("F" + digits) + "z";
default: default:
return (d * 1e24).ToString("F" + digits) + "y"; return (d * 1e24).ToString("F" + digits) + "y";
} }
} }
else else
{ {
return "0"; return "0";
} }
} }
   
public static string ConvertInterval(double seconds) 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_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_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"; string format_3 = "{0:D2}h {1:D2}m {2:D2}.{3:D1}s";
   
TimeSpan interval; TimeSpan interval;
   
try try
{ {
interval = TimeSpan.FromSeconds(seconds); interval = TimeSpan.FromSeconds(seconds);
} }
catch (OverflowException) catch (OverflowException)
{ {
return "NaN"; return "NaN";
} }
   
int years = interval.Days / 365; int years = interval.Days / 365;
   
string output; string output;
if (years > 0) if (years > 0)
{ {
output = string.Format(format_1, output = string.Format(format_1,
years, years,
interval.Days - (years * 365), // subtract years * 365 for accurate day count interval.Days - (years * 365), // subtract years * 365 for accurate day count
interval.Hours, interval.Hours,
interval.Minutes, interval.Minutes,
interval.Seconds, interval.Seconds,
interval.Milliseconds.ToString().Substring(0, 1)); interval.Milliseconds.ToString().Substring(0, 1));
} }
else if (interval.Days > 0) else if (interval.Days > 0)
{ {
output = string.Format(format_2, output = string.Format(format_2,
interval.Days, interval.Days,
interval.Hours, interval.Hours,
interval.Minutes, interval.Minutes,
interval.Seconds, interval.Seconds,
interval.Milliseconds.ToString().Substring(0, 1)); interval.Milliseconds.ToString().Substring(0, 1));
} }
else else
{ {
output = string.Format(format_3, output = string.Format(format_3,
interval.Hours, interval.Hours,
interval.Minutes, interval.Minutes,
interval.Seconds, interval.Seconds,
interval.Milliseconds.ToString().Substring(0, 1)); interval.Milliseconds.ToString().Substring(0, 1));
} }
return output; return output;
} }
   
public static string UppercaseFirst(string s) public static string UppercaseFirst(string s)
{ {
if (string.IsNullOrEmpty(s)) if (string.IsNullOrEmpty(s))
{ {
return string.Empty; return string.Empty;
} }
char[] a = s.ToCharArray(); char[] a = s.ToCharArray();
a[0] = char.ToUpper(a[0]); a[0] = char.ToUpper(a[0]);
return new string(a); return new string(a);
} }
   
//transfer angles //transfer angles
   
public static double Nivvy_CalcTransferPhaseAngle(double r_current, double r_target, double grav_param) public static double Nivvy_CalcTransferPhaseAngle(double r_current, double r_target, double grav_param)
{ {
double T_target = (2 * Math.PI) * Math.Sqrt(Math.Pow((r_target / 1000), 3) / (grav_param / 1000000000)); 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)); 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))); return 360 * (0.5 - (T_transfer / (2 * T_target)));
} }
   
public static double Younata_DeltaVToGetToOtherBody(double mu, double r1, double r2) public static double Younata_DeltaVToGetToOtherBody(double mu, double r1, double r2)
{ {
/* /*
def deltaVToGetToOtherBody(mu, r1, r2): def deltaVToGetToOtherBody(mu, r1, r2):
# mu = gravity param of common orbiting body of r1 and r2 # mu = gravity param of common orbiting body of r1 and r2
# (e.g. for mun to minmus, mu is kerbin's gravity param # (e.g. for mun to minmus, mu is kerbin's gravity param
# r1 = initial body's orbit radius # r1 = initial body's orbit radius
# r2 = target body's orbit radius # r2 = target body's orbit radius
# return value is km/s # return value is km/s
sur1 = math.sqrt(mu / r1) sur1 = math.sqrt(mu / r1)
sr1r2 = math.sqrt(float(2*r2)/float(r1+r2)) sr1r2 = math.sqrt(float(2*r2)/float(r1+r2))
mult = sr1r2 - 1 mult = sr1r2 - 1
return sur1 * mult return sur1 * mult
*/ */
double sur1, sr1r2, mult; double sur1, sr1r2, mult;
sur1 = Math.Sqrt(mu / r1); sur1 = Math.Sqrt(mu / r1);
sr1r2 = Math.Sqrt((2 * r2) / (r1 + r2)); sr1r2 = Math.Sqrt((2 * r2) / (r1 + r2));
mult = sr1r2 - 1; mult = sr1r2 - 1;
return sur1 * mult; return sur1 * mult;
} }
   
public static double Younata_DeltaVToExitSOI(double mu, double r1, double r2, double v) public static double Younata_DeltaVToExitSOI(double mu, double r1, double r2, double v)
{ {
/* /*
def deltaVToExitSOI(mu, r1, r2, v): def deltaVToExitSOI(mu, r1, r2, v):
# mu = gravity param of current body # mu = gravity param of current body
# r1 = current orbit radius # r1 = current orbit radius
# r2 = SOI radius # r2 = SOI radius
# v = SOI exit velocity # v = SOI exit velocity
foo = r2 * (v**2) - 2 * mu foo = r2 * (v**2) - 2 * mu
bar = r1 * foo + (2 * r2 * mu) bar = r1 * foo + (2 * r2 * mu)
r = r1*r2 r = r1*r2
return math.sqrt(bar / r) return math.sqrt(bar / r)
*/ */
double foo = r2 * Math.Pow(v, 2) - 2 * mu; double foo = r2 * Math.Pow(v, 2) - 2 * mu;
double bar = r1 * foo + (2 * r2 * mu); double bar = r1 * foo + (2 * r2 * mu);
double r = r1 * r2; double r = r1 * r2;
return Math.Sqrt(bar / r); return Math.Sqrt(bar / r);
} }
   
public static double Younata_TransferBurnPoint(double r, double v, double angle, double mu) public static double Younata_TransferBurnPoint(double r, double v, double angle, double mu)
{ {
/* /*
def transferBurnPoint(r, v, angle, mu): def transferBurnPoint(r, v, angle, mu):
# r = parking orbit radius # r = parking orbit radius
# v = ejection velocity # v = ejection velocity
# angle = phase angle (from function phaseAngle()) # angle = phase angle (from function phaseAngle())
# mu = gravity param of current body. # mu = gravity param of current body.
epsilon = ((v**2)/2) - (mu / r) epsilon = ((v**2)/2) - (mu / r)
h = r * v * math.sin(angle) h = r * v * math.sin(angle)
e = math.sqrt(1 + ((2 * epsilon * h**2)/(mu**2))) e = math.sqrt(1 + ((2 * epsilon * h**2)/(mu**2)))
theta = math.acos(1.0 / e) theta = math.acos(1.0 / e)
degrees = theta * (180.0 / math.pi) degrees = theta * (180.0 / math.pi)
return 180 - degrees return 180 - degrees
*/ */
double epsilon, h, ee, theta, degrees; double epsilon, h, ee, theta, degrees;
epsilon = (Math.Pow(v, 2) / 2) - (mu / r); epsilon = (Math.Pow(v, 2) / 2) - (mu / r);
h = r * v * Math.Sin(angle); h = r * v * Math.Sin(angle);
ee = Math.Sqrt(1 + ((2 * epsilon * Math.Pow(h, 2)) / Math.Pow(mu, 2))); ee = Math.Sqrt(1 + ((2 * epsilon * Math.Pow(h, 2)) / Math.Pow(mu, 2)));
theta = Math.Acos(1.0 / ee); theta = Math.Acos(1.0 / ee);
degrees = theta * (180.0 / Math.PI); degrees = theta * (180.0 / Math.PI);
return 180 - degrees; return 180 - degrees;
// returns the ejection angle // returns the ejection angle
} }
   
public static double Adammada_CurrrentPhaseAngle(double body_LAN, double body_orbitPct, double origin_LAN, double origin_orbitPct) 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); double angle = (body_LAN / 360 + body_orbitPct) - (origin_LAN / 360 + origin_orbitPct);
if (angle > 1) angle = angle - 1; if (angle > 1)
if (angle < 0) angle = angle + 1; angle = angle - 1;
if (angle > 0.5) angle = angle - 1; if (angle < 0)
  angle = angle + 1;
  if (angle > 0.5)
  angle = angle - 1;
angle = angle * 360; angle = angle * 360;
return angle; return angle;
} }
   
public static double Adammada_CurrentEjectionAngle(double vessel_long, double origin_rotAngle, double origin_LAN, double origin_orbitPct) 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 = ((FlightGlobals.ActiveVOID.vessel.longitude + orbiting.rotationAngle) - (orbiting.orbit.LAN / 360 + orbiting.orbit.orbitPercent) * 360);
double eangle = ((vessel_long + origin_rotAngle) - (origin_LAN / 360 + origin_orbitPct) * 360); double eangle = ((vessel_long + origin_rotAngle) - (origin_LAN / 360 + origin_orbitPct) * 360);
   
while (eangle < 0) eangle = eangle + 360; while (eangle < 0)
while (eangle > 360) eangle = eangle - 360; eangle = eangle + 360;
if (eangle < 270) eangle = 90 - eangle; while (eangle > 360)
else eangle = 450 - eangle; eangle = eangle - 360;
  if (eangle < 270)
  eangle = 90 - eangle;
  else
  eangle = 450 - eangle;
return eangle; return eangle;
} }
   
public static double mrenigma03_calcphase(Vessel vessel, CelestialBody target) //calculates phase angle between the current body and target body public static double mrenigma03_calcphase(Vessel vessel, CelestialBody target) //calculates phase angle between the current body and target body
{ {
Vector3d vecthis = new Vector3d(); Vector3d vecthis = new Vector3d();
Vector3d vectarget = new Vector3d(); Vector3d vectarget = new Vector3d();
vectarget = target.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime()); vectarget = target.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime());
   
if ((vessel.mainBody.name == "Sun") || (vessel.mainBody.referenceBody.referenceBody.name == "Sun")) if ((vessel.mainBody.name == "Sun") || (vessel.mainBody.referenceBody.referenceBody.name == "Sun"))
{ {
vecthis = vessel.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime()); vecthis = vessel.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime());
} }
else else
{ {
vecthis = vessel.mainBody.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime()); vecthis = vessel.mainBody.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime());
} }
   
vecthis = Vector3d.Project(new Vector3d(vecthis.x, 0, vecthis.z), vecthis); vecthis = Vector3d.Project(new Vector3d(vecthis.x, 0, vecthis.z), vecthis);
vectarget = Vector3d.Project(new Vector3d(vectarget.x, 0, vectarget.z), vectarget); vectarget = Vector3d.Project(new Vector3d(vectarget.x, 0, vectarget.z), vectarget);
   
Vector3d prograde = new Vector3d(); Vector3d prograde = new Vector3d();
prograde = Quaternion.AngleAxis(90, Vector3d.forward) * vecthis; prograde = Quaternion.AngleAxis(90, Vector3d.forward) * vecthis;
   
double phase = Vector3d.Angle(vecthis, vectarget); double phase = Vector3d.Angle(vecthis, vectarget);
   
if (Vector3d.Angle(prograde, vectarget) > 90) phase = 360 - phase; if (Vector3d.Angle(prograde, vectarget) > 90)
  phase = 360 - phase;
   
return (phase + 360) % 360; return (phase + 360) % 360;
} }
   
public static double FixAngleDomain(double Angle, bool Degrees = false) public static double FixAngleDomain(double Angle, bool Degrees = false)
{ {
double Extent = 2d * Math.PI; double Extent = 2d * Math.PI;
if (Degrees) { if (Degrees)
  {
Extent = 360d; Extent = 360d;
} }
   
Angle = Angle % (Extent); Angle = Angle % (Extent);
if (Angle < 0d) if (Angle < 0d)
{ {
Angle += Extent; Angle += Extent;
} }
   
return Angle; return Angle;
} }
   
public static double FixDegreeDomain(double Angle) public static double FixDegreeDomain(double Angle)
{ {
return FixAngleDomain (Angle, true); return FixAngleDomain(Angle, true);
} }
   
public static double adjustCurrPhaseAngle(double transfer_angle, double curr_phase) public static double adjustCurrPhaseAngle(double transfer_angle, double curr_phase)
{ {
if (transfer_angle < 0) if (transfer_angle < 0)
{ {
if (curr_phase > 0) return (-1 * (360 - curr_phase)); if (curr_phase > 0)
else if (curr_phase < 0) return curr_phase; return (-1 * (360 - curr_phase));
  else if (curr_phase < 0)
  return curr_phase;
} }
else if (transfer_angle > 0) else if (transfer_angle > 0)
{ {
if (curr_phase > 0) return curr_phase; if (curr_phase > 0)
else if (curr_phase < 0) return (360 + curr_phase); return curr_phase;
  else if (curr_phase < 0)
  return (360 + curr_phase);
} }
return curr_phase; return curr_phase;
} }
   
public static double adjust_current_ejection_angle(double curr_ejection) public static double adjust_current_ejection_angle(double curr_ejection)
{ {
//curr_ejection WILL need to be adjusted once for all transfers as it returns values ranging -180 to 180 //curr_ejection WILL need to be adjusted once for all transfers as it returns values ranging -180 to 180
// need 0-360 instead // need 0-360 instead
// //
// ie i have -17 in the screenshot // ie i have -17 in the screenshot
// need it to show 343 // need it to show 343
// //
// do this // do this
// //
// if < 0, add curr to 360 // 360 + (-17) = 343 // if < 0, add curr to 360 // 360 + (-17) = 343
// else its good as it is // else its good as it is
   
if (curr_ejection < 0) return 360 + curr_ejection; if (curr_ejection < 0)
else return curr_ejection; return 360 + curr_ejection;
  else
  return curr_ejection;
   
} }
   
public static double adjust_transfer_ejection_angle(double trans_ejection, double trans_phase) public static double adjust_transfer_ejection_angle(double trans_ejection, double trans_phase)
{ {
// if transfer_phase_angle < 0 its a lower transfer // if transfer_phase_angle < 0 its a lower transfer
//180 + curr_ejection //180 + curr_ejection
// else if transfer_phase_angle > 0 its good as it is // else if transfer_phase_angle > 0 its good as it is
   
if (trans_phase < 0) return 180 + trans_ejection; if (trans_phase < 0)
else return trans_ejection; return 180 + trans_ejection;
  else
  return trans_ejection;
   
} }
   
public static double TrueAltitude(Vessel vessel) public static double TrueAltitude(Vessel vessel)
{ {
double trueAltitude = vessel.orbit.altitude - vessel.terrainAltitude; double trueAltitude = vessel.orbit.altitude - vessel.terrainAltitude;
   
// HACK: This assumes that on worlds with oceans, all water is fixed at 0 m, // HACK: This assumes that on worlds with oceans, all water is fixed at 0 m,
// and water covers the whole surface at 0 m. // and water covers the whole surface at 0 m.
if (vessel.terrainAltitude < 0 && vessel.mainBody.ocean ) if (vessel.terrainAltitude < 0 && vessel.mainBody.ocean)
{ {
trueAltitude = vessel.orbit.altitude; trueAltitude = vessel.orbit.altitude;
} }
   
return trueAltitude; return trueAltitude;
} }
   
public static string get_heading_text(double heading) public static string get_heading_text(double heading)
{ {
if (heading > 348.75 || heading <= 11.25) return "N"; if (heading > 348.75 || heading <= 11.25)
else if (heading > 11.25 && heading <= 33.75) return "NNE"; return "N";
else if (heading > 33.75 && heading <= 56.25) return "NE"; else if (heading > 11.25 && heading <= 33.75)
else if (heading > 56.25 && heading <= 78.75) return "ENE"; return "NNE";
else if (heading > 78.75 && heading <= 101.25) return "E"; else if (heading > 33.75 && heading <= 56.25)
else if (heading > 101.25 && heading <= 123.75) return "ESE"; return "NE";
else if (heading > 123.75 && heading <= 146.25) return "SE"; else if (heading > 56.25 && heading <= 78.75)
else if (heading > 146.25 && heading <= 168.75) return "SSE"; return "ENE";
else if (heading > 168.75 && heading <= 191.25) return "S"; else if (heading > 78.75 && heading <= 101.25)
else if (heading > 191.25 && heading <= 213.75) return "SSW"; return "E";
else if (heading > 213.75 && heading <= 236.25) return "SW"; else if (heading > 101.25 && heading <= 123.75)
else if (heading > 236.25 && heading <= 258.75) return "WSW"; return "ESE";
else if (heading > 258.75 && heading <= 281.25) return "W"; else if (heading > 123.75 && heading <= 146.25)
else if (heading > 281.25 && heading <= 303.75) return "WNW"; return "SE";
else if (heading > 303.75 && heading <= 326.25) return "NW"; else if (heading > 146.25 && heading <= 168.75)
else if (heading > 326.25 && heading <= 348.75) return "NNW"; return "SSE";
else return ""; 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) public static void display_transfer_angles_SUN2PLANET(CelestialBody body, Vessel vessel)
{ {
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Phase angle (curr/trans):"); GUILayout.Label("Phase angle (curr/trans):");
GUILayout.Label(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.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.EndHorizontal();
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Transfer velocity:"); 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.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(); GUILayout.EndHorizontal();
} }
   
public static void display_transfer_angles_PLANET2PLANET(CelestialBody body, Vessel vessel) public static void display_transfer_angles_PLANET2PLANET(CelestialBody body, Vessel vessel)
{ {
double dv1 = Tools.Younata_DeltaVToGetToOtherBody((vessel.mainBody.referenceBody.gravParameter / 1000000000), (vessel.mainBody.orbit.semiMajorAxis / 1000), (body.orbit.semiMajorAxis / 1000)); double dv1 = Tools.Younata_DeltaVToGetToOtherBody(
double dv2 = Tools.Younata_DeltaVToExitSOI((vessel.mainBody.gravParameter / 1000000000), (vessel.orbit.semiMajorAxis / 1000), (vessel.mainBody.sphereOfInfluence / 1000), Math.Abs(dv1)); (vessel.mainBody.referenceBody.gravParameter / 1000000000),
  (vessel.mainBody.orbit.semiMajorAxis / 1000),
double trans_ejection_angle = Tools.Younata_TransferBurnPoint((vessel.orbit.semiMajorAxis / 1000), dv2, (Math.PI / 2.0), (vessel.mainBody.gravParameter / 1000000000)); (body.orbit.semiMajorAxis / 1000)
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 dv2 = Tools.Younata_DeltaVToExitSOI(
double trans_phase_angle = Tools.Nivvy_CalcTransferPhaseAngle(vessel.mainBody.orbit.semiMajorAxis, body.orbit.semiMajorAxis, vessel.mainBody.referenceBody.gravParameter) % 360; (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); (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_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_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); double adj_curr_ejection_angle = Tools.adjust_current_ejection_angle(curr_ejection_angle);
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Phase angle (curr/trans):"); GUILayout.Label("Phase angle (curr/trans):");
GUILayout.Label(adj_phase_angle.ToString("F3") + "° / " + trans_phase_angle.ToString("F3") + "°", GUILayout.ExpandWidth(false)); GUILayout.Label(
  adj_phase_angle.ToString("F3") + "° / " + trans_phase_angle.ToString("F3") + "°",
  GUILayout.ExpandWidth(false)
  );
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Ejection angle (curr/trans):"); GUILayout.Label("Ejection angle (curr/trans):");
GUILayout.Label(adj_curr_ejection_angle.ToString("F3") + "° / " + adj_trans_ejection_angle.ToString("F3") + "°", GUILayout.ExpandWidth(false)); GUILayout.Label(
  adj_curr_ejection_angle.ToString("F3") + "° / " + adj_trans_ejection_angle.ToString("F3") + "°",
  GUILayout.ExpandWidth(false)
  );
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Transfer velocity:"); GUILayout.Label("Transfer velocity:");
GUILayout.Label((dv2 * 1000).ToString("F2") + "m/s", GUILayout.ExpandWidth(false)); GUILayout.Label((dv2 * 1000).ToString("F2") + "m/s", GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
   
public static void display_transfer_angles_PLANET2MOON(CelestialBody body, Vessel vessel) public static void display_transfer_angles_PLANET2MOON(CelestialBody body, Vessel vessel)
{ {
double dv1 = Tools.Younata_DeltaVToGetToOtherBody((vessel.mainBody.gravParameter / 1000000000), (vessel.orbit.semiMajorAxis / 1000), (body.orbit.semiMajorAxis / 1000)); double dv1 = Tools.Younata_DeltaVToGetToOtherBody(
  (vessel.mainBody.gravParameter / 1000000000),
double trans_phase_angle = Tools.Nivvy_CalcTransferPhaseAngle(vessel.orbit.semiMajorAxis, body.orbit.semiMajorAxis, vessel.mainBody.gravParameter); (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.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Phase angle (curr/trans):"); GUILayout.Label("Phase angle (curr/trans):");
GUILayout.Label(Tools.mrenigma03_calcphase(vessel, body).ToString("F3") + "° / " + trans_phase_angle.ToString("F3") + "°", GUILayout.ExpandWidth(false)); GUILayout.Label(
  Tools.mrenigma03_calcphase(vessel, body).ToString("F3") + "° / " + trans_phase_angle.ToString("F3") + "°",
  GUILayout.ExpandWidth(false)
  );
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Transfer velocity:"); GUILayout.Label("Transfer velocity:");
GUILayout.Label((dv1 * 1000).ToString("F2") + "m/s", GUILayout.ExpandWidth(false)); GUILayout.Label((dv1 * 1000).ToString("F2") + "m/s", GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
   
public static void display_transfer_angles_MOON2MOON(CelestialBody body, Vessel vessel) public static void display_transfer_angles_MOON2MOON(CelestialBody body, Vessel vessel)
{ {
double dv1 = Tools.Younata_DeltaVToGetToOtherBody((vessel.mainBody.referenceBody.gravParameter / 1000000000), (vessel.mainBody.orbit.semiMajorAxis / 1000), (body.orbit.semiMajorAxis / 1000)); double dv1 = Tools.Younata_DeltaVToGetToOtherBody(
double dv2 = Tools.Younata_DeltaVToExitSOI((vessel.mainBody.gravParameter / 1000000000), (vessel.orbit.semiMajorAxis / 1000), (vessel.mainBody.sphereOfInfluence / 1000), Math.Abs(dv1)); (vessel.mainBody.referenceBody.gravParameter / 1000000000),
double trans_ejection_angle = Tools.Younata_TransferBurnPoint((vessel.orbit.semiMajorAxis / 1000), dv2, (Math.PI / 2.0), (vessel.mainBody.gravParameter / 1000000000)); (vessel.mainBody.orbit.semiMajorAxis / 1000),
  (body.orbit.semiMajorAxis / 1000)
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 dv2 = Tools.Younata_DeltaVToExitSOI(
  (vessel.mainBody.gravParameter / 1000000000),
double trans_phase_angle = Tools.Nivvy_CalcTransferPhaseAngle(vessel.mainBody.orbit.semiMajorAxis, body.orbit.semiMajorAxis, vessel.mainBody.referenceBody.gravParameter) % 360; (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_phase_angle = Tools.adjustCurrPhaseAngle(trans_phase_angle, curr_phase_angle);
//double adj_ejection_angle = adjustCurrEjectionAngle(trans_phase_angle, curr_ejection_angle); //double adj_ejection_angle = adjustCurrEjectionAngle(trans_phase_angle, curr_ejection_angle);
   
//new stuff //new stuff
// //
double adj_trans_ejection_angle = Tools.adjust_transfer_ejection_angle(trans_ejection_angle, trans_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); double adj_curr_ejection_angle = Tools.adjust_current_ejection_angle(curr_ejection_angle);
// //
// //
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Phase angle (curr/trans):"); GUILayout.Label("Phase angle (curr/trans):");
GUILayout.Label(adj_phase_angle.ToString("F3") + "° / " + trans_phase_angle.ToString("F3") + "°", GUILayout.ExpandWidth(false)); GUILayout.Label(
  adj_phase_angle.ToString("F3") + "° / " + trans_phase_angle.ToString("F3") + "°",
  GUILayout.ExpandWidth(false)
  );
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Ejection angle (curr/trans):"); GUILayout.Label("Ejection angle (curr/trans):");
GUILayout.Label(adj_curr_ejection_angle.ToString("F3") + "° / " + adj_trans_ejection_angle.ToString("F3") + "°", GUILayout.ExpandWidth(false)); GUILayout.Label(
  adj_curr_ejection_angle.ToString("F3") + "° / " + adj_trans_ejection_angle.ToString("F3") + "°",
  GUILayout.ExpandWidth(false)
  );
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Transfer velocity:"); GUILayout.Label("Transfer velocity:");
GUILayout.Label((dv2 * 1000).ToString("F2") + "m/s", GUILayout.ExpandWidth(false)); GUILayout.Label((dv2 * 1000).ToString("F2") + "m/s", GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
   
// This implementation is adapted from FARGUIUtils.ClampToScreen // This implementation is adapted from FARGUIUtils.ClampToScreen
public static Rect ClampRectToScreen(Rect window, int xMargin, int yMargin) public static Rect ClampRectToScreen(Rect window, int xMargin, int yMargin)
{ {
window.x = Mathf.Clamp (window.x, xMargin - window.width, Screen.width - xMargin); window.x = Mathf.Clamp(window.x, xMargin - window.width, Screen.width - xMargin);
window.y = Mathf.Clamp (window.y, yMargin - window.height, Screen.height - yMargin); window.y = Mathf.Clamp(window.y, yMargin - window.height, Screen.height - yMargin);
   
return window; return window;
} }
   
public static Rect ClampRectToScreen(Rect window, int Margin) public static Rect ClampRectToScreen(Rect window, int Margin)
{ {
return ClampRectToScreen(window, Margin, Margin); return ClampRectToScreen(window, Margin, Margin);
} }
   
public static Rect ClampRectToScreen(Rect window) public static Rect ClampRectToScreen(Rect window)
{ {
return ClampRectToScreen (window, 30); return ClampRectToScreen(window, 30);
} }
   
public static Vector2 ClampV2ToScreen(Vector2 vec, uint xMargin, uint yMargin) public static Vector2 ClampV2ToScreen(Vector2 vec, uint xMargin, uint yMargin)
{ {
vec.x = Mathf.Clamp (vec.x, xMargin, Screen.width - xMargin); vec.x = Mathf.Clamp(vec.x, xMargin, Screen.width - xMargin);
vec.y = Mathf.Clamp (vec.y, yMargin, Screen.height - yMargin); vec.y = Mathf.Clamp(vec.y, yMargin, Screen.height - yMargin);
   
return vec; return vec;
} }
   
public static Vector2 ClampV2ToScreen(Vector2 vec, uint Margin) public static Vector2 ClampV2ToScreen(Vector2 vec, uint Margin)
{ {
return ClampV2ToScreen(vec, Margin, Margin); return ClampV2ToScreen(vec, Margin, Margin);
} }
   
public static Vector2 ClampV2ToScreen(Vector2 vec) public static Vector2 ClampV2ToScreen(Vector2 vec)
{ {
return ClampV2ToScreen (vec, 15); return ClampV2ToScreen(vec, 15);
} }
   
// UNDONE: This seems messy. Can we clean it up? // UNDONE: This seems messy. Can we clean it up?
public static Rect DockToWindow(Rect icon, Rect window) 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. // We can't set the x and y of the center point directly, so build a new vector.
Vector2 center = new Vector2 (); Vector2 center = new Vector2();
   
// If we are near the top or bottom of the screen... // If we are near the top or bottom of the screen...
if (window.yMax > Screen.height - icon.height || if (window.yMax > Screen.height - icon.height ||
window.yMin < icon.height window.yMin < icon.height)
)  
{ {
// If we are in a corner... // If we are in a corner...
if (window.xMax > Screen.width - icon.width || if (window.xMax > Screen.width - icon.width ||
window.xMin < icon.width window.xMin < icon.width)
)  
{ {
// If it is a top corner, put the icon below the window. // If it is a top corner, put the icon below the window.
if (window.yMax < Screen.height / 2) if (window.yMax < Screen.height / 2)
{ {
center.y = window.yMax + icon.height / 2; center.y = window.yMax + icon.height / 2;
} }
// If it is a bottom corner, put the icon above the window. // If it is a bottom corner, put the icon above the window.
else else
{ {
center.y = window.yMin - icon.height / 2; center.y = window.yMin - icon.height / 2;
} }
} }
// If we are not in a corner... // If we are not in a corner...
else else
{ {
// If we are along the top edge, align the icon's top edge with the top edge of the window // 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) if (window.yMax > Screen.height / 2)
{ {
center.y = window.yMax - icon.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 // If we are along the bottom edge, align the icon's bottom edge with the bottom edge of the window
else else
{ {
center.y = window.yMin + icon.height / 2; 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 // 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) if (window.center.x < Screen.width / 2)
{ {
center.x = window.xMin - icon.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 // At the top or bottom, if we are towards the left, put the icon to the left of the window
else else
{ {
center.x = window.xMax + icon.width / 2; center.x = window.xMax + icon.width / 2;
} }
   
} }
// If we are not along the top or bottom of the screen... // If we are not along the top or bottom of the screen...
else else
{ {
// By default, center the icon above the window // By default, center the icon above the window
center.y = window.yMin - icon.height / 2; center.y = window.yMin - icon.height / 2;
center.x = window.center.x; center.x = window.center.x;
   
// If we are along a side... // If we are along a side...
if (window.xMax > Screen.width - icon.width || if (window.xMax > Screen.width - icon.width ||
window.xMin < icon.width window.xMin < icon.width)
)  
{ {
// UNDONE: I'm not sure I like the feel of this part. // 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 we are along a side towards the bottom, put the icon below the window
if (window.center.y > Screen.height / 2) if (window.center.y > Screen.height / 2)
{ {
center.y = window.yMax + icon.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. // 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) if (window.xMax > Screen.width - icon.width)
{ {
center.x = window.xMax - icon.width / 2; 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. // Along the right side, align the right edge of the icon with the right edge of the window.
else if (window.xMin < icon.width) else if (window.xMin < icon.width)
{ {
center.x = window.xMin + icon.width / 2; center.x = window.xMin + icon.width / 2;
} }
} }
} }
   
// Assign the vector to the center of the rect. // Assign the vector to the center of the rect.
icon.center = center; icon.center = center;
   
// Return the icon's position. // Return the icon's position.
return icon; 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 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); private static ScreenMessage debugmsg = new ScreenMessage("", 2f, ScreenMessageStyle.UPPER_RIGHT);
   
[System.Diagnostics.Conditional("DEBUG")] [System.Diagnostics.Conditional("DEBUG")]
public static void PostDebugMessage(string Msg) public static void PostDebugMessage(string Msg)
{ {
if (HighLogic.LoadedScene > GameScenes.SPACECENTER) if (HighLogic.LoadedScene > GameScenes.SPACECENTER)
{ {
debugmsg.message = Msg; debugmsg.message = Msg;
ScreenMessages.PostScreenMessage(debugmsg, true); ScreenMessages.PostScreenMessage(debugmsg, true);
} }
   
KSPLog.print(Msg); KSPLog.print(Msg);
} }
} }
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
// VOID - Vessel Orbital Information Display for Kerbal Space Program // VOID - Vessel Orbital Information Display for Kerbal Space Program
// Copyright (C) 2012 Iannic-ann-od // Copyright (C) 2012 Iannic-ann-od
// Copyright (C) 2013 Toadicus // Copyright (C) 2013 Toadicus
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
// Much, much credit to Younata, Adammada, Nivvydaskrl and to all the authors // Much, much credit to Younata, Adammada, Nivvydaskrl and to all the authors
// behind MechJeb, RemoteTech Relay Network, ISA MapSat, and Protractor for some // behind MechJeb, RemoteTech Relay Network, ISA MapSat, and Protractor for some
// invaluable functions and making your nicely written code available to learn from. // invaluable functions and making your nicely written code available to learn from.
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
// This software uses VesselSimulator and Engineer.Extensions from Engineer Redux. // This software uses VesselSimulator and Engineer.Extensions from Engineer Redux.
// Engineer Redux (c) 2013 cybutek // Engineer Redux (c) 2013 cybutek
// Used by permission. // Used by permission.
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
   
using System; using System;
using System.Collections.Generic;  
using System.Linq;  
using UnityEngine; using UnityEngine;
using Engineer.VesselSimulator; using Engineer.VesselSimulator;
   
namespace VOID namespace VOID
{ {
[KSPAddon(KSPAddon.Startup.Flight, false)] [KSPAddon(KSPAddon.Startup.Flight, false)]
public class VOIDFlightMaster : MonoBehaviour public class VOIDFlightMaster : MonoBehaviour
{ {
protected VOID_Core Core; protected VOID_Core Core;
   
public void Awake() public void Awake()
{ {
Tools.PostDebugMessage ("VOIDFlightMaster: Waking up."); Tools.PostDebugMessage ("VOIDFlightMaster: Waking up.");
this.Core = (VOID_Core)VOID_Core.Instance; this.Core = (VOID_Core)VOID_Core.Instance;
this.Core.ResetGUI (); this.Core.ResetGUI ();
SimManager.HardReset(); SimManager.HardReset();
Tools.PostDebugMessage ("VOIDFlightMaster: Awake."); Tools.PostDebugMessage ("VOIDFlightMaster: Awake.");
} }
   
public void Update() public void Update()
{ {
if (!HighLogic.LoadedSceneIsFlight && this.Core != null) if (!HighLogic.LoadedSceneIsFlight && this.Core != null)
{ {
this.Core.SaveConfig (); this.Core.SaveConfig ();
this.Core = null; this.Core = null;
VOID_Core.Reset(); VOID_Core.Reset();
return; return;
} }
   
if (this.Core == null) if (this.Core == null)
{ {
this.Awake(); this.Awake();
} }
   
this.Core.Update (); this.Core.Update ();
   
if (this.Core.factoryReset) if (this.Core.factoryReset)
{ {
KSP.IO.File.Delete<VOID_Core>("config.xml"); KSP.IO.File.Delete<VOID_Core>("config.xml");
this.Core = null; this.Core = null;
VOID_Core.Reset(); VOID_Core.Reset();
} }
} }
   
public void FixedUpdate() public void FixedUpdate()
{ {
if (this.Core == null || !HighLogic.LoadedSceneIsFlight) if (this.Core == null || !HighLogic.LoadedSceneIsFlight)
{ {
return; return;
} }
   
this.Core.FixedUpdate (); this.Core.FixedUpdate ();
} }
   
public void OnGUI() public void OnGUI()
{ {
if (this.Core == null) if (this.Core == null)
{ {
return; return;
} }
   
this.Core.OnGUI(); this.Core.OnGUI();
} }
} }
   
[KSPAddon(KSPAddon.Startup.EditorAny, false)] [KSPAddon(KSPAddon.Startup.EditorAny, false)]
public class VOIDEditorMaster : MonoBehaviour public class VOIDEditorMaster : MonoBehaviour
{ {
protected VOID_EditorCore Core; protected VOID_EditorCore Core;
   
public void Awake() public void Awake()
{ {
Tools.PostDebugMessage ("VOIDEditorMaster: Waking up."); Tools.PostDebugMessage ("VOIDEditorMaster: Waking up.");
this.Core = VOID_EditorCore.Instance; this.Core = VOID_EditorCore.Instance;
this.Core.ResetGUI (); this.Core.ResetGUI ();
SimManager.HardReset(); SimManager.HardReset();
Tools.PostDebugMessage ("VOIDEditorMaster: Awake."); Tools.PostDebugMessage ("VOIDEditorMaster: Awake.");
} }
   
public void Update() public void Update()
{ {
if (!HighLogic.LoadedSceneIsEditor && this.Core != null) if (!HighLogic.LoadedSceneIsEditor && this.Core != null)
{ {
this.Core.SaveConfig (); this.Core.SaveConfig ();
this.Core = null; this.Core = null;
VOID_EditorCore.Reset(); VOID_EditorCore.Reset();
return; return;
} }
   
if (this.Core == null) if (this.Core == null)
{ {
this.Awake(); this.Awake();
} }
   
this.Core.Update (); this.Core.Update ();
   
if (this.Core.factoryReset) if (this.Core.factoryReset)
{ {
KSP.IO.File.Delete<VOID_EditorCore>("config.xml"); KSP.IO.File.Delete<VOID_EditorCore>("config.xml");
this.Core = null; this.Core = null;
VOID_EditorCore.Reset(); VOID_EditorCore.Reset();
} }
} }
   
public void FixedUpdate() public void FixedUpdate()
{ {
if (this.Core == null || !HighLogic.LoadedSceneIsEditor) if (this.Core == null || !HighLogic.LoadedSceneIsEditor)
{ {
return; return;
} }
   
this.Core.FixedUpdate (); this.Core.FixedUpdate ();
} }
   
public void OnGUI() public void OnGUI()
{ {
if (this.Core == null) if (this.Core == null)
{ {
return; return;
} }
   
this.Core.OnGUI(); this.Core.OnGUI();
} }
} }
} }
   
// //
// VOID_Core.cs // VOID_Core.cs
// //
// Author: // Author:
// toadicus <> // toadicus <>
// //
// Copyright (c) 2013 toadicus // Copyright (c) 2013 toadicus
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using KSP; using KSP;
using UnityEngine; using UnityEngine;
using Engineer.VesselSimulator; using Engineer.VesselSimulator;
   
namespace VOID namespace VOID
{ {
public class VOID_Core : VOID_Module, IVOID_Module public class VOID_Core : VOID_Module, IVOID_Module
{ {
/* /*
* Static Members * Static Members
* */ * */
protected static bool _initialized = false; protected static bool _initialized = false;
   
public static bool Initialized public static bool Initialized
{ {
get get
{ {
return _initialized; return _initialized;
} }
} }
   
protected static VOID_Core _instance; protected static VOID_Core _instance;
   
public static VOID_Core Instance public static VOID_Core Instance
{ {
get get
{ {
if (_instance == null) if (_instance == null)
{ {
_instance = new VOID_Core(); _instance = new VOID_Core();
_initialized = true; _initialized = true;
} }
return _instance; return _instance;
} }
} }
   
public static void Reset() public static void Reset()
{ {
_instance.StopGUI(); _instance.StopGUI();
_instance = null; _instance = null;
_initialized = false; _initialized = false;
} }
   
public static double Constant_G = 6.674e-11; public static double Constant_G = 6.674e-11;
   
/* /*
* Fields * Fields
* */ * */
protected string VoidName = "VOID"; protected string VoidName = "VOID";
protected string VoidVersion = "0.9.15"; protected string VoidVersion = "0.9.20";
   
protected bool _factoryReset = false; protected bool _factoryReset = false;
   
[AVOID_SaveValue("configValue")] [AVOID_SaveValue("configValue")]
protected VOID_SaveValue<int> configVersion = 1; protected VOID_SaveValue<int> configVersion = 1;
   
protected List<IVOID_Module> _modules = new List<IVOID_Module>(); protected List<IVOID_Module> _modules = new List<IVOID_Module>();
protected bool _modulesLoaded = false; protected bool _modulesLoaded = false;
   
[AVOID_SaveValue("mainWindowPos")] [AVOID_SaveValue("mainWindowPos")]
protected VOID_SaveValue<Rect> mainWindowPos = new Rect(475, 575, 10f, 10f); protected VOID_SaveValue<Rect> mainWindowPos = new Rect(475, 575, 10f, 10f);
   
[AVOID_SaveValue("mainGuiMinimized")] [AVOID_SaveValue("mainGuiMinimized")]
protected VOID_SaveValue<bool> mainGuiMinimized = false; protected VOID_SaveValue<bool> mainGuiMinimized = false;
   
[AVOID_SaveValue("configWindowPos")] [AVOID_SaveValue("configWindowPos")]
protected VOID_SaveValue<Rect> configWindowPos = new Rect(825, 625, 10f, 10f); protected VOID_SaveValue<Rect> configWindowPos = new Rect(825, 625, 10f, 10f);
   
[AVOID_SaveValue("configWindowMinimized")] [AVOID_SaveValue("configWindowMinimized")]
protected VOID_SaveValue<bool> configWindowMinimized = true; protected VOID_SaveValue<bool> configWindowMinimized = true;
   
[AVOID_SaveValue("VOIDIconPos")] [AVOID_SaveValue("VOIDIconPos")]
protected VOID_SaveValue<Rect> VOIDIconPos = new Rect(Screen.width / 2 - 200, Screen.height - 30, 30f, 30f); protected VOID_SaveValue<Rect> VOIDIconPos = new Rect(Screen.width / 2 - 200, Screen.height - 32, 32f, 32f);
protected Texture2D VOIDIconOff = new Texture2D(30, 30, TextureFormat.ARGB32, false); protected Texture2D VOIDIconOff;
protected Texture2D VOIDIconOn = new Texture2D(30, 30, TextureFormat.ARGB32, false); protected Texture2D VOIDIconOn;
protected Texture2D VOIDIconTexture; protected Texture2D VOIDIconTexture;
protected string VOIDIconOnPath = "VOID/Textures/void_icon_on"; protected string VOIDIconOnPath = "VOID/Textures/void_icon_on";
protected string VOIDIconOffPath = "VOID/Textures/void_icon_off"; protected string VOIDIconOffPath = "VOID/Textures/void_icon_off";
protected bool VOIDIconLocked = true; protected bool VOIDIconLocked = true;
  protected GUIStyle iconStyle;
protected int windowBaseID = -96518722; protected int windowBaseID = -96518722;
protected int _windowID = 0; protected int _windowID = 0;
   
protected bool GUIStylesLoaded = false; protected bool GUIStylesLoaded = false;
   
protected Dictionary<string, GUIStyle> _LabelStyles = new Dictionary<string, GUIStyle>(); protected Dictionary<string, GUIStyle> _LabelStyles = new Dictionary<string, GUIStyle>();
   
[AVOID_SaveValue("togglePower")] [AVOID_SaveValue("togglePower")]
public VOID_SaveValue<bool> togglePower = true; public VOID_SaveValue<bool> togglePower = true;
   
public bool powerAvailable = true; public bool powerAvailable = true;
   
[AVOID_SaveValue("consumeResource")] [AVOID_SaveValue("consumeResource")]
protected VOID_SaveValue<bool> consumeResource = false; protected VOID_SaveValue<bool> consumeResource = false;
   
[AVOID_SaveValue("resourceName")] [AVOID_SaveValue("resourceName")]
protected VOID_SaveValue<string> resourceName = "ElectricCharge"; protected VOID_SaveValue<string> resourceName = "ElectricCharge";
   
[AVOID_SaveValue("resourceRate")] [AVOID_SaveValue("resourceRate")]
protected VOID_SaveValue<float> resourceRate = 0.2f; protected VOID_SaveValue<float> resourceRate = 0.2f;
   
[AVOID_SaveValue("updatePeriod")] [AVOID_SaveValue("updatePeriod")]
protected VOID_SaveValue<double> _updatePeriod = 1001f/15000f; protected VOID_SaveValue<double> _updatePeriod = 1001f / 15000f;
protected float _updateTimer = 0f; protected float _updateTimer = 0f;
protected string stringFrequency; protected string stringFrequency;
   
// Celestial Body Housekeeping // Celestial Body Housekeeping
protected List<CelestialBody> _allBodies = new List<CelestialBody>(); protected List<CelestialBody> _allBodies = new List<CelestialBody>();
protected bool bodiesLoaded = false; protected bool bodiesLoaded = false;
   
// Vessel Type Housekeeping // Vessel Type Housekeeping
protected List<VesselType> _allVesselTypes = new List<VesselType>(); protected List<VesselType> _allVesselTypes = new List<VesselType>();
protected bool vesselTypesLoaded = false; protected bool vesselTypesLoaded = false;
   
public float saveTimer = 0; public float saveTimer = 0;
   
protected string defaultSkin = "KSP window 2"; protected string defaultSkin = "KSP window 2";
   
[AVOID_SaveValue("defaultSkin")] [AVOID_SaveValue("defaultSkin")]
protected VOID_SaveValue<string> _skinName; protected VOID_SaveValue<string> _skinName;
protected Dictionary<string, GUISkin> skin_list; protected Dictionary<string, GUISkin> skin_list;
protected List<string> skinNames; protected List<string> skinNames;
protected string[] forbiddenSkins = protected string[] forbiddenSkins =
{ {
"PlaqueDialogSkin", "PlaqueDialogSkin",
"FlagBrowserSkin", "FlagBrowserSkin",
"SSUITextAreaDefault", "SSUITextAreaDefault",
"ExperimentsDialogSkin", "ExperimentsDialogSkin",
"ExpRecoveryDialogSkin", "ExpRecoveryDialogSkin",
"KSP window 5", "KSP window 5",
"KSP window 6" "KSP window 6",
}; "PartTooltipSkin"
  };
protected bool skinsLoaded = false; protected bool skinsLoaded = false;
   
public bool configDirty; public bool configDirty;
  [AVOID_SaveValue("UseBlizzyToolbar")]
protected bool ToolbarManagerLoaded = false; protected VOID_SaveValue<bool> _UseToolbarManager;
protected bool _UseToolbarManager; protected bool ToolbarManagerLoaded;
internal ToolbarButtonWrapper ToolbarButton; internal ToolbarButtonWrapper ToolbarButton;
   
/* /*
* Properties * Properties
* */ * */
public bool factoryReset public bool factoryReset
{ {
get get
{ {
return this._factoryReset; return this._factoryReset;
} }
} }
   
public List<IVOID_Module> Modules public List<IVOID_Module> Modules
{ {
get get
{ {
return this._modules; return this._modules;
} }
} }
   
public GUISkin Skin public GUISkin Skin
{ {
get get
{ {
if (!this.skinsLoaded || this._skinName == null) if (!this.skinsLoaded || this._skinName == null)
{ {
return AssetBase.GetGUISkin(this.defaultSkin); return AssetBase.GetGUISkin(this.defaultSkin);
} }
return this.skin_list[this._skinName]; return this.skin_list[this._skinName];
} }
} }
   
public int windowID public int windowID
{ {
get get
{ {
if (this._windowID == 0) if (this._windowID == 0)
{ {
this._windowID = this.windowBaseID; this._windowID = this.windowBaseID;
} }
return this._windowID++; return this._windowID++;
} }
} }
   
public Dictionary<string, GUIStyle> LabelStyles public Dictionary<string, GUIStyle> LabelStyles
{ {
get get
{ {
return this._LabelStyles; return this._LabelStyles;
} }
} }
   
public List<CelestialBody> allBodies public List<CelestialBody> allBodies
{ {
get get
{ {
return this._allBodies; return this._allBodies;
} }
} }
   
public List<VesselType> allVesselTypes public List<VesselType> allVesselTypes
{ {
get get
{ {
return this._allVesselTypes; return this._allVesselTypes;
} }
} }
   
public float updateTimer public float updateTimer
{ {
get get
{ {
return this._updateTimer; return this._updateTimer;
} }
} }
   
public double updatePeriod public double updatePeriod
{ {
get get
{ {
return this._updatePeriod; return this._updatePeriod;
} }
} }
   
protected bool UseToolbarManager protected bool UseToolbarManager
{ {
get get
{ {
return _UseToolbarManager; return _UseToolbarManager;
} }
set set
{ {
if (value == false && this.ToolbarManagerLoaded && this.ToolbarButton != null) if (value == false && this.ToolbarManagerLoaded && this.ToolbarButton != null)
{ {
this.ToolbarButton.Destroy(); this.ToolbarButton.Destroy();
this.ToolbarButton = null; this.ToolbarButton = null;
} }
if (value == true && this.ToolbarManagerLoaded && this.ToolbarButton == null) if (value == true && this.ToolbarManagerLoaded && this.ToolbarButton == null)
{ {
this.InitializeToolbarButton(); this.InitializeToolbarButton();
} }
   
_UseToolbarManager = value; _UseToolbarManager.value = value;
} }
} }
   
/* /*
* Methods * Methods
* */ * */
protected VOID_Core() protected VOID_Core()
{ {
this._Name = "VOID Core"; this._Name = "VOID Core";
   
this._Active.value = true; this._Active.value = true;
   
this.VOIDIconOn = GameDatabase.Instance.GetTexture (this.VOIDIconOnPath, false); this.VOIDIconOn = GameDatabase.Instance.GetTexture(this.VOIDIconOnPath, false);
this.VOIDIconOff = GameDatabase.Instance.GetTexture (this.VOIDIconOffPath, false); this.VOIDIconOff = GameDatabase.Instance.GetTexture(this.VOIDIconOffPath, false);
   
this._skinName = this.defaultSkin; this._skinName = this.defaultSkin;
   
this.UseToolbarManager = false; this.UseToolbarManager = false;
  this.ToolbarManagerLoaded = false;
this.LoadConfig ();  
} this.LoadConfig();
  }
   
protected void LoadModulesOfType<T>() protected void LoadModulesOfType<T>()
{ {
var types = AssemblyLoader.loadedAssemblies var types = AssemblyLoader.loadedAssemblies
.Select (a => a.assembly.GetExportedTypes ()) .Select(a => a.assembly.GetExportedTypes())
.SelectMany (t => t) .SelectMany(t => t)
.Where (v => typeof(T).IsAssignableFrom (v) .Where(v => typeof(T).IsAssignableFrom(v)
&& !(v.IsInterface || v.IsAbstract) && && !(v.IsInterface || v.IsAbstract) &&
!typeof(VOID_Core).IsAssignableFrom (v) !typeof(VOID_Core).IsAssignableFrom(v)
); );
   
Tools.PostDebugMessage (string.Format ( Tools.PostDebugMessage(string.Format(
"{0}: Found {1} modules to check.", "{0}: Found {1} modules to check.",
this.GetType ().Name, this.GetType().Name,
types.Count () 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
)); ));
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.LoadModule(voidType);
} }
   
this._modulesLoaded = true; this._modulesLoaded = true;
   
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: Loaded {1} modules.", "{0}: Loaded {1} modules.",
this.GetType().Name, this.GetType().Name,
this.Modules.Count this.Modules.Count
)); ));
} }
   
protected void LoadModule(Type T) protected void LoadModule(Type T)
{ {
var existingModules = this._modules.Where (mod => mod.GetType ().Name == T.Name); var existingModules = this._modules.Where(mod => mod.GetType().Name == T.Name);
if (existingModules.Any()) if (existingModules.Any())
{ {
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: refusing to load {1}: already loaded", "{0}: refusing to load {1}: already loaded",
this.GetType().Name, this.GetType().Name,
T.Name T.Name
)); ));
return; return;
} }
IVOID_Module module = Activator.CreateInstance (T) as IVOID_Module; IVOID_Module module = Activator.CreateInstance(T) as IVOID_Module;
module.LoadConfig(); module.LoadConfig();
this._modules.Add (module); this._modules.Add(module);
   
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: loaded module {1}.", "{0}: loaded module {1}.",
this.GetType().Name, this.GetType().Name,
T.Name T.Name
)); ));
} }
   
protected void LoadSkins() protected void LoadSkins()
{ {
Tools.PostDebugMessage ("AssetBase has skins: \n" + Tools.PostDebugMessage("AssetBase has skins: \n" +
string.Join("\n\t", AssetBase.FindObjectsOfTypeIncludingAssets ( string.Join("\n\t",
typeof(GUISkin)) Resources.FindObjectsOfTypeAll(typeof(GUISkin))
.Select(s => s.ToString()) .Select(s => s.ToString())
.ToArray() .ToArray()
) )
); );
   
this.skin_list = AssetBase.FindObjectsOfTypeIncludingAssets(typeof(GUISkin)) this.skin_list = Resources.FindObjectsOfTypeAll(typeof(GUISkin))
.Where(s => !this.forbiddenSkins.Contains(s.name)) .Where(s => !this.forbiddenSkins.Contains(s.name))
.Select(s => s as GUISkin) .Select(s => s as GUISkin)
.GroupBy(s => s.name) .GroupBy(s => s.name)
.Select(g => g.First()) .Select(g => g.First())
.ToDictionary(s => s.name); .ToDictionary(s => s.name);
   
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: loaded {1} GUISkins.", "{0}: loaded {1} GUISkins.",
this.GetType().Name, this.GetType().Name,
this.skin_list.Count this.skin_list.Count
)); ));
   
this.skinNames = this.skin_list.Keys.ToList(); this.skinNames = this.skin_list.Keys.ToList();
this.skinNames.Sort(); this.skinNames.Sort();
   
if (this._skinName == null || !this.skinNames.Contains(this._skinName)) if (this._skinName == null || !this.skinNames.Contains(this._skinName))
{ {
this._skinName = this.defaultSkin; this._skinName = this.defaultSkin;
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: resetting _skinIdx to default.", "{0}: resetting _skinIdx to default.",
this.GetType().Name this.GetType().Name
)); ));
} }
   
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: _skinIdx = {1}.", "{0}: _skinIdx = {1}.",
this.GetType().Name, this.GetType().Name,
this._skinName.ToString() this._skinName.ToString()
)); ));
   
this.skinsLoaded = true; this.skinsLoaded = true;
} }
   
protected void LoadGUIStyles() protected void LoadGUIStyles()
{ {
this.LabelStyles["link"] = new GUIStyle(GUI.skin.label); this.LabelStyles["link"] = new GUIStyle(GUI.skin.label);
this.LabelStyles["link"].fontStyle = FontStyle.Bold; this.LabelStyles["link"].fontStyle = FontStyle.Bold;
   
this.LabelStyles["center"] = new GUIStyle(GUI.skin.label); this.LabelStyles["center"] = new GUIStyle(GUI.skin.label);
this.LabelStyles["center"].normal.textColor = Color.white; this.LabelStyles["center"].normal.textColor = Color.white;
this.LabelStyles["center"].alignment = TextAnchor.UpperCenter; this.LabelStyles["center"].alignment = TextAnchor.UpperCenter;
   
this.LabelStyles["center_bold"] = new GUIStyle(GUI.skin.label); this.LabelStyles["center_bold"] = new GUIStyle(GUI.skin.label);
this.LabelStyles["center_bold"].normal.textColor = Color.white; this.LabelStyles["center_bold"].normal.textColor = Color.white;
this.LabelStyles["center_bold"].alignment = TextAnchor.UpperCenter; this.LabelStyles["center_bold"].alignment = TextAnchor.UpperCenter;
this.LabelStyles["center_bold"].fontStyle = FontStyle.Bold; this.LabelStyles["center_bold"].fontStyle = FontStyle.Bold;
   
this.LabelStyles["right"] = new GUIStyle(GUI.skin.label); this.LabelStyles["right"] = new GUIStyle(GUI.skin.label);
this.LabelStyles["right"].normal.textColor = Color.white; this.LabelStyles["right"].normal.textColor = Color.white;
this.LabelStyles["right"].alignment = TextAnchor.UpperRight; this.LabelStyles["right"].alignment = TextAnchor.UpperRight;
   
this.LabelStyles ["red"] = new GUIStyle(GUI.skin.label); this.LabelStyles["red"] = new GUIStyle(GUI.skin.label);
this.LabelStyles ["red"].normal.textColor = Color.red; this.LabelStyles["red"].normal.textColor = Color.red;
this.LabelStyles ["red"].alignment = TextAnchor.MiddleCenter; 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; this.GUIStylesLoaded = true;
} }
   
protected void LoadAllBodies() protected void LoadAllBodies()
{ {
this._allBodies = FlightGlobals.Bodies; this._allBodies = FlightGlobals.Bodies;
this.bodiesLoaded = true; this.bodiesLoaded = true;
} }
   
protected void LoadVesselTypes() protected void LoadVesselTypes()
{ {
this._allVesselTypes = Enum.GetValues(typeof(VesselType)).OfType<VesselType>().ToList(); this._allVesselTypes = Enum.GetValues(typeof(VesselType)).OfType<VesselType>().ToList();
this.vesselTypesLoaded = true; this.vesselTypesLoaded = true;
} }
   
protected void LoadBeforeUpdate() protected void LoadBeforeUpdate()
{ {
if (!this.bodiesLoaded) if (!this.bodiesLoaded)
{ {
this.LoadAllBodies(); this.LoadAllBodies();
} }
   
if (!this.vesselTypesLoaded) if (!this.vesselTypesLoaded)
{ {
this.LoadVesselTypes(); this.LoadVesselTypes();
} }
} }
   
protected void LoadToolbarManager() protected void LoadToolbarManager()
{ {
Type ToolbarManager = AssemblyLoader.loadedAssemblies this.ToolbarManagerLoaded = ToolbarButtonWrapper.ToolbarManagerPresent;
.Select(a => a.assembly.GetExportedTypes())  
.SelectMany(t => t) if (this.ToolbarManagerLoaded)
.FirstOrDefault(t => t.FullName == "Toolbar.ToolbarManager"); {
  this.InitializeToolbarButton();
if (ToolbarManager == null) }
{  
Tools.PostDebugMessage(string.Format(  
"{0}: Could not load ToolbarManager.",  
this.GetType().Name  
));  
   
return;  
}  
   
this.InitializeToolbarButton();  
   
this.ToolbarManagerLoaded = true;  
} }
   
protected void InitializeToolbarButton() protected void InitializeToolbarButton()
{ {
this.ToolbarButton = new ToolbarButtonWrapper(this.GetType().Name, "coreToggle"); this.ToolbarButton = ToolbarButtonWrapper.TryWrapToolbarButton(this.GetType().Name, "coreToggle");
this.ToolbarButton.Text = this.VoidName; this.ToolbarButton.Text = this.VoidName;
this.ToolbarButton.TexturePath = this.VOIDIconOffPath + "_24x24"; this.ToolbarButton.TexturePath = this.VOIDIconOffPath;
  if (this is VOID_EditorCore)
  {
  this.ToolbarButton.SetButtonVisibility(new GameScenes[] { GameScenes.EDITOR });
  }
  else
  {
  this.ToolbarButton.SetButtonVisibility(new GameScenes[] { GameScenes.FLIGHT });
  }
this.ToolbarButton.AddButtonClickHandler( this.ToolbarButton.AddButtonClickHandler(
(e) => this.mainGuiMinimized = !this.mainGuiMinimized (e) => this.mainGuiMinimized = !this.mainGuiMinimized
); );
} }
   
public void VOIDMainWindow(int _) public void VOIDMainWindow(int _)
{ {
GUILayout.BeginVertical(); GUILayout.BeginVertical();
if (this.powerAvailable || HighLogic.LoadedSceneIsEditor) if (this.powerAvailable || HighLogic.LoadedSceneIsEditor)
{ {
if (!HighLogic.LoadedSceneIsEditor) if (!HighLogic.LoadedSceneIsEditor)
{ {
string str = "ON"; string str = "ON";
if (togglePower) str = "OFF"; if (togglePower)
if (GUILayout.Button("Power " + str)) togglePower.value = !togglePower; str = "OFF";
  if (GUILayout.Button("Power " + str))
  togglePower.value = !togglePower;
} }
   
if (togglePower || HighLogic.LoadedSceneIsEditor) if (togglePower || HighLogic.LoadedSceneIsEditor)
{ {
foreach (IVOID_Module module in this.Modules) foreach (IVOID_Module module in this.Modules)
{ {
module.toggleActive = GUILayout.Toggle (module.toggleActive, module.Name); module.toggleActive = GUILayout.Toggle(module.toggleActive, module.Name);
} }
} }
} }
else else
{ {
GUILayout.Label("-- POWER LOST --", this.LabelStyles["red"]); GUILayout.Label("-- POWER LOST --", this.LabelStyles["red"]);
} }
   
this.configWindowMinimized.value = !GUILayout.Toggle (!this.configWindowMinimized, "Configuration"); this.configWindowMinimized.value = !GUILayout.Toggle(!this.configWindowMinimized, "Configuration");
   
GUILayout.EndVertical(); GUILayout.EndVertical();
GUI.DragWindow(); GUI.DragWindow();
} }
   
public void VOIDConfigWindow(int _) public void VOIDConfigWindow(int _)
{ {
GUILayout.BeginVertical (); GUILayout.BeginVertical();
   
this.DrawConfigurables (); this.DrawConfigurables();
   
GUILayout.EndVertical (); GUILayout.EndVertical();
GUI.DragWindow (); GUI.DragWindow();
} }
   
public override void DrawConfigurables() public override void DrawConfigurables()
{ {
int skinIdx; int skinIdx;
   
GUIContent _content; GUIContent _content;
   
if (HighLogic.LoadedSceneIsFlight) if (HighLogic.LoadedSceneIsFlight)
{ {
this.consumeResource.value = GUILayout.Toggle (this.consumeResource, "Consume Resources"); this.consumeResource.value = GUILayout.Toggle(this.consumeResource, "Consume Resources");
   
this.VOIDIconLocked = GUILayout.Toggle (this.VOIDIconLocked, "Lock Icon Position"); this.VOIDIconLocked = GUILayout.Toggle(this.VOIDIconLocked, "Lock Icon Position");
} }
   
this.UseToolbarManager = GUILayout.Toggle(this.UseToolbarManager, "Use Blizzy's Toolbar"); this.UseToolbarManager = GUILayout.Toggle(this.UseToolbarManager, "Use Blizzy's Toolbar If Available");
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
   
GUILayout.Label("Skin:", GUILayout.ExpandWidth(false)); GUILayout.Label("Skin:", GUILayout.ExpandWidth(false));
   
_content = new GUIContent(); _content = new GUIContent();
   
if (skinNames.Contains(this._skinName)) if (skinNames.Contains(this._skinName))
{ {
skinIdx = skinNames.IndexOf(this._skinName); skinIdx = skinNames.IndexOf(this._skinName);
} }
else if (skinNames.Contains(this.defaultSkin)) else if (skinNames.Contains(this.defaultSkin))
{ {
skinIdx = skinNames.IndexOf(this.defaultSkin); skinIdx = skinNames.IndexOf(this.defaultSkin);
} }
else else
{ {
skinIdx = 0; skinIdx = 0;
} }
   
_content.text = "◄"; _content.text = "◄";
_content.tooltip = "Select previous skin"; _content.tooltip = "Select previous skin";
if (GUILayout.Button(_content, GUILayout.ExpandWidth(true))) if (GUILayout.Button(_content, GUILayout.ExpandWidth(true)))
{ {
  this.GUIStylesLoaded = false;
skinIdx--; skinIdx--;
if (skinIdx < 0) skinIdx = skinNames.Count - 1; if (skinIdx < 0)
Tools.PostDebugMessage (string.Format ( skinIdx = skinNames.Count - 1;
  Tools.PostDebugMessage(string.Format(
"{0}: new this._skinIdx = {1} :: skin_list.Count = {2}", "{0}: new this._skinIdx = {1} :: skin_list.Count = {2}",
this.GetType().Name, this.GetType().Name,
this._skinName, this._skinName,
this.skin_list.Count this.skin_list.Count
)); ));
} }
   
_content.text = this.Skin.name; _content.text = this.Skin.name;
_content.tooltip = "Current skin"; _content.tooltip = "Current skin";
GUILayout.Label(_content, this.LabelStyles["center"], GUILayout.ExpandWidth(true)); GUILayout.Label(_content, this.LabelStyles["center"], GUILayout.ExpandWidth(true));
   
_content.text = "►"; _content.text = "►";
_content.tooltip = "Select next skin"; _content.tooltip = "Select next skin";
if (GUILayout.Button(_content, GUILayout.ExpandWidth(true))) if (GUILayout.Button(_content, GUILayout.ExpandWidth(true)))
{ {
  this.GUIStylesLoaded = false;
skinIdx++; skinIdx++;
if (skinIdx >= skinNames.Count) skinIdx = 0; if (skinIdx >= skinNames.Count)
Tools.PostDebugMessage (string.Format ( skinIdx = 0;
  Tools.PostDebugMessage(string.Format(
"{0}: new this._skinIdx = {1} :: skin_list.Count = {2}", "{0}: new this._skinIdx = {1} :: skin_list.Count = {2}",
this.GetType().Name, this.GetType().Name,
this._skinName, this._skinName,
this.skin_list.Count this.skin_list.Count
)); ));
} }
   
if (this._skinName != skinNames[skinIdx]) if (this._skinName != skinNames[skinIdx])
{ {
this._skinName = skinNames[skinIdx]; this._skinName = skinNames[skinIdx];
} }
   
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(); GUILayout.BeginHorizontal();
GUILayout.Label("Update Rate (Hz):"); GUILayout.Label("Update Rate (Hz):");
if (this.stringFrequency == null) if (this.stringFrequency == null)
{ {
this.stringFrequency = (1f / this.updatePeriod).ToString(); this.stringFrequency = (1f / this.updatePeriod).ToString();
} }
this.stringFrequency = GUILayout.TextField(this.stringFrequency.ToString(), 5, GUILayout.ExpandWidth(true)); this.stringFrequency = GUILayout.TextField(this.stringFrequency.ToString(), 5, GUILayout.ExpandWidth(true));
// GUILayout.FlexibleSpace(); // GUILayout.FlexibleSpace();
if (GUILayout.Button("Apply")) if (GUILayout.Button("Apply"))
{ {
double updateFreq = 1f / this.updatePeriod; double updateFreq = 1f / this.updatePeriod;
double.TryParse(stringFrequency, out updateFreq); double.TryParse(stringFrequency, out updateFreq);
this._updatePeriod = 1 / updateFreq; this._updatePeriod = 1 / updateFreq;
} }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
foreach (IVOID_Module mod in this.Modules) foreach (IVOID_Module mod in this.Modules)
{ {
mod.DrawConfigurables (); mod.DrawConfigurables();
} }
   
this._factoryReset = GUILayout.Toggle (this._factoryReset, "Factory Reset"); this._factoryReset = GUILayout.Toggle(this._factoryReset, "Factory Reset");
} }
   
public override void DrawGUI() public override void DrawGUI()
{ {
this._windowID = this.windowBaseID; this._windowID = this.windowBaseID;
   
if (!this._modulesLoaded) if (!this._modulesLoaded)
{ {
this.LoadModulesOfType<IVOID_Module> (); this.LoadModulesOfType<IVOID_Module>();
} }
   
if (this.UseToolbarManager && !this.ToolbarManagerLoaded) if (this.UseToolbarManager && !this.ToolbarManagerLoaded)
{ {
this.LoadToolbarManager(); this.LoadToolbarManager();
} }
   
if (!this.skinsLoaded) if (!this.skinsLoaded)
{ {
this.LoadSkins(); this.LoadSkins();
} }
   
GUI.skin = this.Skin; GUI.skin = this.Skin;
   
if (!this.GUIStylesLoaded) if (!this.GUIStylesLoaded)
{ {
this.LoadGUIStyles (); this.LoadGUIStyles();
} }
   
if (this.UseToolbarManager && this.ToolbarManagerLoaded) if (this.UseToolbarManager && this.ToolbarManagerLoaded)
{ {
this.ToolbarButton.TexturePath = VOIDIconOffPath + "_24x24"; this.ToolbarButton.TexturePath = VOIDIconOffPath;
if (this.togglePower) if (this.togglePower)
{ {
this.ToolbarButton.TexturePath = VOIDIconOnPath + "_24x24"; this.ToolbarButton.TexturePath = VOIDIconOnPath;
} }
} }
else else
{ {
this.VOIDIconTexture = this.VOIDIconOff; //icon off default this.VOIDIconTexture = this.VOIDIconOff; //icon off default
if (this.togglePower) if (this.togglePower)
this.VOIDIconTexture = this.VOIDIconOn; //or on if power_toggle==true this.VOIDIconTexture = this.VOIDIconOn; //or on if power_toggle==true
if (GUI.Button(VOIDIconPos, VOIDIconTexture, new GUIStyle()) && this.VOIDIconLocked)  
  if (GUI.Button(VOIDIconPos, VOIDIconTexture, this.iconStyle) && this.VOIDIconLocked)
{ {
this.mainGuiMinimized.value = !this.mainGuiMinimized; this.mainGuiMinimized.value = !this.mainGuiMinimized;
} }
} }
   
if (!this.mainGuiMinimized) if (!this.mainGuiMinimized)
{ {
Rect _mainWindowPos = this.mainWindowPos; Rect _mainWindowPos = this.mainWindowPos;
   
_mainWindowPos = GUILayout.Window ( _mainWindowPos = GUILayout.Window(
this.windowID, this.windowID,
_mainWindowPos, _mainWindowPos,
this.VOIDMainWindow, this.VOIDMainWindow,
string.Join (" ", new string[] {this.VoidName, this.VoidVersion}), string.Join(" ", new string[] { this.VoidName, this.VoidVersion }),
GUILayout.Width (250), GUILayout.Width(250),
GUILayout.Height (50) GUILayout.Height(50)
); );
   
_mainWindowPos = Tools.ClampRectToScreen (_mainWindowPos); _mainWindowPos = Tools.ClampRectToScreen(_mainWindowPos);
   
if (_mainWindowPos != this.mainWindowPos) if (_mainWindowPos != this.mainWindowPos)
{ {
this.mainWindowPos = _mainWindowPos; this.mainWindowPos = _mainWindowPos;
} }
} }
   
if (!this.configWindowMinimized && !this.mainGuiMinimized) if (!this.configWindowMinimized && !this.mainGuiMinimized)
{ {
Rect _configWindowPos = this.configWindowPos; Rect _configWindowPos = this.configWindowPos;
   
_configWindowPos = GUILayout.Window ( _configWindowPos = GUILayout.Window(
this.windowID, this.windowID,
_configWindowPos, _configWindowPos,
this.VOIDConfigWindow, this.VOIDConfigWindow,
string.Join (" ", new string[] {this.VoidName, "Configuration"}), string.Join(" ", new string[] { this.VoidName, "Configuration" }),
GUILayout.Width (250), GUILayout.Width(250),
GUILayout.Height (50) GUILayout.Height(50)
); );
   
_configWindowPos = Tools.ClampRectToScreen (_configWindowPos); _configWindowPos = Tools.ClampRectToScreen(_configWindowPos);
   
if (_configWindowPos != this.configWindowPos) if (_configWindowPos != this.configWindowPos)
{ {
this.configWindowPos = _configWindowPos; this.configWindowPos = _configWindowPos;
} }
} }
} }
   
public void OnGUI() public void OnGUI()
{ {
if (Event.current.type == EventType.Repaint) if (Event.current.type == EventType.Repaint)
{ {
return; return;
} }
   
/* /*
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"Event.current.type: {0}" + "Event.current.type: {0}" +
"\nthis.VOIDIconLocked: {1}" + "\nthis.VOIDIconLocked: {1}" +
"\nEvent.current.mousePosition: {2}" + "\nEvent.current.mousePosition: {2}" +
"\nVOIDIconPos: ({3}, {4}),({5}, {6})", "\nVOIDIconPos: ({3}, {4}),({5}, {6})",
Event.current.type, Event.current.type,
this.VOIDIconLocked, this.VOIDIconLocked,
Event.current.mousePosition, Event.current.mousePosition,
this.VOIDIconPos.value.xMin, this.VOIDIconPos.value.xMin,
this.VOIDIconPos.value.yMin, this.VOIDIconPos.value.yMin,
this.VOIDIconPos.value.xMax, this.VOIDIconPos.value.xMax,
this.VOIDIconPos.value.yMax this.VOIDIconPos.value.yMax
)); ));
*/ */
   
if (!this.VOIDIconLocked && if (!this.VOIDIconLocked &&
VOIDIconPos.value.Contains(Event.current.mousePosition) VOIDIconPos.value.Contains(Event.current.mousePosition)
&& Event.current.type == EventType.mouseDrag && Event.current.type == EventType.mouseDrag)
)  
{ {
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"Event.current.type: {0}" + "Event.current.type: {0}" +
"\ndelta.x: {1}; delta.y: {2}", "\ndelta.x: {1}; delta.y: {2}",
Event.current.type, Event.current.type,
Event.current.delta.x, Event.current.delta.x,
Event.current.delta.y Event.current.delta.y
)); ));
   
Rect tmp = new Rect(VOIDIconPos); Rect tmp = new Rect(VOIDIconPos);
   
tmp.x = Event.current.mousePosition.x - tmp.width / 2; tmp.x = Event.current.mousePosition.x - tmp.width / 2;
tmp.y = Event.current.mousePosition.y - tmp.height / 2; tmp.y = Event.current.mousePosition.y - tmp.height / 2;
   
if (tmp.x > Screen.width - tmp.width) if (tmp.x > Screen.width - tmp.width)
{ {
tmp.x = Screen.width - tmp.width; tmp.x = Screen.width - tmp.width;
} }
   
if (tmp.y > Screen.height - tmp.height) if (tmp.y > Screen.height - tmp.height)
{ {
tmp.y = Screen.height - tmp.height; tmp.y = Screen.height - tmp.height;
} }
   
VOIDIconPos = tmp; VOIDIconPos = tmp;
} }
} }
   
public void Update() public void Update()
{ {
this.LoadBeforeUpdate (); this.LoadBeforeUpdate();
   
if (this.vessel != null) if (this.vessel != null)
{ {
SimManager.Instance.Gravity = VOID_Core.Instance.vessel.mainBody.gravParameter / SimManager.Instance.Gravity = VOID_Core.Instance.vessel.mainBody.gravParameter /
Math.Pow(VOID_Core.Instance.vessel.mainBody.Radius, 2); Math.Pow(VOID_Core.Instance.vessel.mainBody.Radius, 2);
SimManager.Instance.TryStartSimulation(); SimManager.Instance.TryStartSimulation();
} }
   
if (!this.guiRunning) if (!this.guiRunning)
{ {
this.StartGUI (); this.StartGUI();
} }
   
if (!HighLogic.LoadedSceneIsFlight && this.guiRunning) if (!HighLogic.LoadedSceneIsFlight && this.guiRunning)
{ {
this.StopGUI (); this.StopGUI();
} }
   
foreach (IVOID_Module module in this.Modules) foreach (IVOID_Module module in this.Modules)
{ {
if (!module.guiRunning && module.toggleActive) if (!module.guiRunning && module.toggleActive)
{ {
module.StartGUI (); module.StartGUI();
} }
if (module.guiRunning && !module.toggleActive || if (module.guiRunning && !module.toggleActive ||
!this.togglePower || !this.togglePower ||
!HighLogic.LoadedSceneIsFlight || !HighLogic.LoadedSceneIsFlight ||
this.factoryReset this.factoryReset)
)  
{ {
module.StopGUI(); module.StopGUI();
} }
   
if (module is IVOID_BehaviorModule) if (module is IVOID_BehaviorModule)
{ {
((IVOID_BehaviorModule)module).Update(); ((IVOID_BehaviorModule)module).Update();
} }
} }
   
this.CheckAndSave (); this.CheckAndSave();
this._updateTimer += Time.deltaTime; this._updateTimer += Time.deltaTime;
} }
   
public void FixedUpdate() public void FixedUpdate()
{ {
if (this.consumeResource && if (this.consumeResource &&
this.vessel.vesselType != VesselType.EVA && this.vessel.vesselType != VesselType.EVA &&
TimeWarp.deltaTime != 0 TimeWarp.deltaTime != 0)
)  
{ {
float powerReceived = this.vessel.rootPart.RequestResource(this.resourceName, float powerReceived = this.vessel.rootPart.RequestResource(this.resourceName,
this.resourceRate * TimeWarp.fixedDeltaTime); this.resourceRate * TimeWarp.fixedDeltaTime);
if (powerReceived > 0) if (powerReceived > 0)
{ {
this.powerAvailable = true; this.powerAvailable = true;
} }
else else
{ {
this.powerAvailable = false; this.powerAvailable = false;
} }
} }
   
foreach (IVOID_BehaviorModule module in foreach (IVOID_BehaviorModule module in
this._modules.OfType<IVOID_BehaviorModule>().Where(m => !m.GetType().IsAbstract)) this._modules.OfType<IVOID_BehaviorModule>().Where(m => !m.GetType().IsAbstract))
{ {
module.FixedUpdate(); module.FixedUpdate();
} }
} }
   
public void ResetGUI() public void ResetGUI()
{ {
this.StopGUI (); this.StopGUI();
   
foreach (IVOID_Module module in this.Modules) foreach (IVOID_Module module in this.Modules)
{ {
module.StopGUI (); module.StopGUI();
module.StartGUI (); module.StartGUI();
} }
   
this.StartGUI (); this.StartGUI();
} }
   
protected void CheckAndSave() protected void CheckAndSave()
{ {
this.saveTimer += Time.deltaTime; this.saveTimer += Time.deltaTime;
   
if (this.saveTimer > 2f) if (this.saveTimer > 2f)
{ {
if (!this.configDirty) if (!this.configDirty)
{ {
return; return;
} }
   
Tools.PostDebugMessage (string.Format ( Tools.PostDebugMessage(string.Format(
"{0}: Time to save, checking if configDirty: {1}", "{0}: Time to save, checking if configDirty: {1}",
this.GetType ().Name, this.GetType().Name,
this.configDirty this.configDirty
)); ));
   
this.SaveConfig (); this.SaveConfig();
this.saveTimer = 0; this.saveTimer = 0;
} }
} }
   
public override void LoadConfig() public override void LoadConfig()
{ {
base.LoadConfig (); base.LoadConfig();
   
foreach (IVOID_Module module in this.Modules) foreach (IVOID_Module module in this.Modules)
{ {
module.LoadConfig (); module.LoadConfig();
} }
} }
   
public void SaveConfig() public void SaveConfig()
{ {
var config = KSP.IO.PluginConfiguration.CreateForType<VOID_Core> (); var config = KSP.IO.PluginConfiguration.CreateForType<VOID_Core>();
config.load (); config.load();
   
this._SaveToConfig(config); this._SaveToConfig(config);
   
foreach (IVOID_Module module in this.Modules) foreach (IVOID_Module module in this.Modules)
{ {
module._SaveToConfig (config); module._SaveToConfig(config);
} }
   
config.save(); config.save();
   
this.configDirty = false; this.configDirty = false;
} }
} }
} }
   
   
// //
// VOID_Hud.cs // VOID_Hud.cs
// //
// Author: // Author:
// toadicus <> // toadicus <>
// //
// Copyright (c) 2013 toadicus // Copyright (c) 2013 toadicus
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
// //
   
using Engineer.VesselSimulator; using Engineer.VesselSimulator;
using KSP; using KSP;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
  using System.Linq;
  using System.Text;
using UnityEngine; using UnityEngine;
   
namespace VOID namespace VOID
{ {
public class VOID_EditorHUD : VOID_Module, IVOID_EditorModule public class VOID_EditorHUD : VOID_Module, IVOID_EditorModule
{ {
/* /*
* Fields * Fields
* */ * */
[AVOID_SaveValue("colorIndex")] [AVOID_SaveValue("colorIndex")]
protected VOID_SaveValue<int> _colorIndex = 0; protected VOID_SaveValue<int> _colorIndex = 0;
   
protected List<Color> textColors = new List<Color>(); protected List<Color> textColors = new List<Color>();
   
protected GUIStyle labelStyle; protected GUIStyle labelStyle;
   
  protected EditorVesselOverlays _vesselOverlays;
   
/* /*
* Properties * Properties
* */ * */
public int ColorIndex public int ColorIndex
{ {
get get
{ {
return this._colorIndex; return this._colorIndex;
} }
set set
{ {
if (this._colorIndex >= this.textColors.Count - 1) if (this._colorIndex >= this.textColors.Count - 1)
{ {
this._colorIndex = 0; this._colorIndex = 0;
return; return;
} }
   
this._colorIndex = value; this._colorIndex = value;
  }
  }
   
  protected EditorVesselOverlays vesselOverlays
  {
  get
  {
  if (this._vesselOverlays == null)
  {
  this._vesselOverlays = (EditorVesselOverlays)Resources
  .FindObjectsOfTypeAll(typeof(EditorVesselOverlays))
  .FirstOrDefault();
  }
   
  return this._vesselOverlays;
  }
  }
   
  protected EditorMarker_CoM CoMmarker
  {
  get
  {
  if (this.vesselOverlays == null)
  {
  return null;
  }
   
  return this.vesselOverlays.CoMmarker;
  }
  }
   
  protected EditorMarker_CoT CoTmarker
  {
  get
  {
  if (this.vesselOverlays == null)
  {
  return null;
  }
   
  return this.vesselOverlays.CoTmarker;
} }
} }
   
/* /*
* Methods * Methods
* */ * */
public VOID_EditorHUD() : base() public VOID_EditorHUD() : base()
{ {
this._Name = "Heads-Up Display"; this._Name = "Heads-Up Display";
   
this._Active.value = true; this._Active.value = true;
   
this.textColors.Add(Color.green); this.textColors.Add(Color.green);
this.textColors.Add(Color.black); this.textColors.Add(Color.black);
this.textColors.Add(Color.white); this.textColors.Add(Color.white);
this.textColors.Add(Color.red); this.textColors.Add(Color.red);
this.textColors.Add(Color.blue); this.textColors.Add(Color.blue);
this.textColors.Add(Color.yellow); this.textColors.Add(Color.yellow);
this.textColors.Add(Color.gray); this.textColors.Add(Color.gray);
this.textColors.Add(Color.cyan); this.textColors.Add(Color.cyan);
this.textColors.Add(Color.magenta); this.textColors.Add(Color.magenta);
   
this.labelStyle = new GUIStyle (); this.labelStyle = new GUIStyle ();
// this.labelStyle.alignment = TextAnchor.UpperRight; // this.labelStyle.alignment = TextAnchor.UpperRight;
this.labelStyle.normal.textColor = this.textColors [this.ColorIndex]; this.labelStyle.normal.textColor = this.textColors [this.ColorIndex];
   
Tools.PostDebugMessage (this.GetType().Name + ": Constructed."); Tools.PostDebugMessage (this.GetType().Name + ": Constructed.");
} }
   
public override void DrawGUI() public override void DrawGUI()
{ {
SimManager.Instance.RequestSimulation(); SimManager.Instance.RequestSimulation();
   
if (SimManager.Instance.LastStage == null) if (SimManager.Instance.LastStage == null)
{ {
return; return;
} }
   
float hudLeft; float hudLeft;
  StringBuilder hudString;
   
if (EditorLogic.fetch.editorScreen == EditorLogic.EditorScreen.Parts) if (EditorLogic.fetch.editorScreen == EditorLogic.EditorScreen.Parts)
{ {
hudLeft = EditorPanels.Instance.partsPanelWidth + 10; hudLeft = EditorPanels.Instance.partsPanelWidth + 10;
} }
else if (EditorLogic.fetch.editorScreen == EditorLogic.EditorScreen.Actions) else if (EditorLogic.fetch.editorScreen == EditorLogic.EditorScreen.Actions)
{ {
hudLeft = EditorPanels.Instance.actionsPanelWidth + 10; hudLeft = EditorPanels.Instance.actionsPanelWidth + 10;
} }
else else
{ {
return; return;
} }
   
Rect hudPos = new Rect (hudLeft, 48, 300, 32); Rect hudPos = new Rect (hudLeft, 48, 300, 32);
   
  hudString = new StringBuilder();
   
// GUI.skin = AssetBase.GetGUISkin("KSP window 2"); // GUI.skin = AssetBase.GetGUISkin("KSP window 2");
   
labelStyle.normal.textColor = textColors [ColorIndex]; labelStyle.normal.textColor = textColors [ColorIndex];
   
  hudString.Append("Total Mass: ");
  hudString.Append(SimManager.Instance.LastStage.totalMass.ToString("F3"));
  hudString.Append('t');
   
  hudString.Append(' ');
   
  hudString.Append("Part Count: ");
  hudString.Append(EditorLogic.SortedShipList.Count);
   
  hudString.Append('\n');
   
  hudString.Append("Total Delta-V: ");
  hudString.Append(Tools.MuMech_ToSI(SimManager.Instance.LastStage.totalDeltaV));
  hudString.Append("m/s");
   
  hudString.Append('\n');
   
  hudString.Append("Bottom Stage Delta-V");
  hudString.Append(Tools.MuMech_ToSI(SimManager.Instance.LastStage.deltaV));
  hudString.Append("m/s");
   
  hudString.Append('\n');
   
  hudString.Append("Bottom Stage T/W Ratio: ");
  hudString.Append(SimManager.Instance.LastStage.thrustToWeight.ToString("F3"));
   
  if (this.CoMmarker.gameObject.activeInHierarchy && this.CoTmarker.gameObject.activeInHierarchy)
  {
  hudString.Append('\n');
   
  hudString.Append("Thrust Offset: ");
  hudString.Append(
  Vector3.Cross(
  this.CoTmarker.dirMarkerObject.transform.forward,
  this.CoMmarker.posMarkerObject.transform.position - this.CoTmarker.posMarkerObject.transform.position
  ).ToString("F3"));
  }
   
GUI.Label ( GUI.Label (
hudPos, hudPos,
"Total Mass: " + SimManager.Instance.LastStage.totalMass.ToString("F3") + "t" + hudString.ToString(),
" Part Count: " + EditorLogic.SortedShipList.Count +  
"\nTotal Delta-V: " + Tools.MuMech_ToSI(SimManager.Instance.LastStage.totalDeltaV) + "m/s" +  
"\nBottom Stage Delta-V: " + Tools.MuMech_ToSI(SimManager.Instance.LastStage.deltaV) + "m/s" +  
"\nBottom Stage T/W Ratio: " + SimManager.Instance.LastStage.thrustToWeight.ToString("F3"),  
labelStyle); labelStyle);
} }
   
public override void DrawConfigurables() public override void DrawConfigurables()
{ {
if (GUILayout.Button ("Change HUD color", GUILayout.ExpandWidth (false))) if (GUILayout.Button ("Change HUD color", GUILayout.ExpandWidth (false)))
{ {
++this.ColorIndex; ++this.ColorIndex;
} }
} }
} }
} }
   
// //
// VOID_Hud.cs // VOID_Hud.cs
// //
// Author: // Author:
// toadicus <> // toadicus <>
// //
// Copyright (c) 2013 toadicus // Copyright (c) 2013 toadicus
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
// //
   
using KSP; using KSP;
using UnityEngine; using UnityEngine;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
   
namespace VOID namespace VOID
{ {
public class VOID_HUD : VOID_Module, IVOID_Module public class VOID_HUD : VOID_Module, IVOID_Module
{ {
/* /*
* Fields * Fields
* */ * */
[AVOID_SaveValue("colorIndex")] [AVOID_SaveValue("colorIndex")]
protected VOID_SaveValue<int> _colorIndex = 0; protected VOID_SaveValue<int> _colorIndex = 0;
   
protected List<Color> textColors = new List<Color>(); protected List<Color> textColors = new List<Color>();
   
/* /*
* Properties * Properties
* */ * */
public int ColorIndex public int ColorIndex
{ {
get get
{ {
return this._colorIndex; return this._colorIndex;
} }
set set
{ {
if (this._colorIndex >= this.textColors.Count - 1) if (this._colorIndex >= this.textColors.Count - 1)
{ {
this._colorIndex = 0; this._colorIndex = 0;
return; return;
} }
   
this._colorIndex = value; this._colorIndex = value;
} }
} }
   
/* /*
* Methods * Methods
* */ * */
public VOID_HUD() : base() public VOID_HUD() : base()
{ {
this._Name = "Heads-Up Display"; this._Name = "Heads-Up Display";
   
this._Active.value = true; this._Active.value = true;
   
this.textColors.Add(Color.green); this.textColors.Add(Color.green);
this.textColors.Add(Color.black); this.textColors.Add(Color.black);
this.textColors.Add(Color.white); this.textColors.Add(Color.white);
this.textColors.Add(Color.red); this.textColors.Add(Color.red);
this.textColors.Add(Color.blue); this.textColors.Add(Color.blue);
this.textColors.Add(Color.yellow); this.textColors.Add(Color.yellow);
this.textColors.Add(Color.gray); this.textColors.Add(Color.gray);
this.textColors.Add(Color.cyan); this.textColors.Add(Color.cyan);
this.textColors.Add(Color.magenta); this.textColors.Add(Color.magenta);
   
VOID_Core.Instance.LabelStyles["hud"] = new GUIStyle(); VOID_Core.Instance.LabelStyles["hud"] = new GUIStyle();
VOID_Core.Instance.LabelStyles["hud"].normal.textColor = this.textColors [this.ColorIndex]; VOID_Core.Instance.LabelStyles["hud"].normal.textColor = this.textColors [this.ColorIndex];
   
Tools.PostDebugMessage ("VOID_HUD: Constructed."); Tools.PostDebugMessage ("VOID_HUD: Constructed.");
} }
   
public override void DrawGUI() public override void DrawGUI()
{ {
GUI.skin = VOID_Core.Instance.Skin; GUI.skin = VOID_Core.Instance.Skin;
   
if (VOID_Core.Instance.powerAvailable) if (VOID_Core.Instance.powerAvailable)
{ {
VOID_Core.Instance.LabelStyles["hud"].normal.textColor = textColors [ColorIndex]; VOID_Core.Instance.LabelStyles["hud"].normal.textColor = textColors [ColorIndex];
   
GUI.Label ( GUI.Label (
new Rect ((Screen.width * .2083f), 0, 300f, 70f), new Rect ((Screen.width * .2083f), 0, 300f, 70f),
"Obt Alt: " + Tools.MuMech_ToSI (vessel.orbit.altitude) + "m" + "Obt Alt: " + Tools.MuMech_ToSI (vessel.orbit.altitude) + "m" +
" Obt Vel: " + Tools.MuMech_ToSI (vessel.orbit.vel.magnitude) + "m/s" + " Obt Vel: " + Tools.MuMech_ToSI (vessel.orbit.vel.magnitude) + "m/s" +
"\nAp: " + Tools.MuMech_ToSI (vessel.orbit.ApA) + "m" + "\nAp: " + Tools.MuMech_ToSI (vessel.orbit.ApA) + "m" +
" ETA " + Tools.ConvertInterval (vessel.orbit.timeToAp) + " ETA " + Tools.ConvertInterval (vessel.orbit.timeToAp) +
"\nPe: " + Tools.MuMech_ToSI (vessel.orbit.PeA) + "m" + "\nPe: " + Tools.MuMech_ToSI (vessel.orbit.PeA) + "m" +
" ETA " + Tools.ConvertInterval (vessel.orbit.timeToPe) + " ETA " + Tools.ConvertInterval (vessel.orbit.timeToPe) +
"\nInc: " + vessel.orbit.inclination.ToString ("F3") + "°" + "\nInc: " + vessel.orbit.inclination.ToString ("F3") + "°" +
"\nPrimary: " + vessel.mainBody.bodyName, "\nPrimary: " + vessel.mainBody.bodyName,
VOID_Core.Instance.LabelStyles["hud"]); VOID_Core.Instance.LabelStyles["hud"]);
// Toadicus edit: Added "Biome: " line to surf/atmo HUD // Toadicus edit: Added "Biome: " line to surf/atmo HUD
GUI.Label ( GUI.Label (
new Rect ((Screen.width * .625f), 0, 300f, 90f), new Rect ((Screen.width * .625f), 0, 300f, 90f),
"Srf Alt: " + Tools.MuMech_ToSI (Tools.TrueAltitude (vessel)) + "m" + "Srf Alt: " + Tools.MuMech_ToSI (Tools.TrueAltitude (vessel)) + "m" +
" Srf Vel: " + Tools.MuMech_ToSI (vessel.srf_velocity.magnitude) + "m/s" + " Srf Vel: " + Tools.MuMech_ToSI (vessel.srf_velocity.magnitude) + "m/s" +
"\nVer: " + Tools.MuMech_ToSI (vessel.verticalSpeed) + "m/s" + "\nVer: " + Tools.MuMech_ToSI (vessel.verticalSpeed) + "m/s" +
" Hor: " + Tools.MuMech_ToSI (vessel.horizontalSrfSpeed) + "m/s" + " Hor: " + Tools.MuMech_ToSI (vessel.horizontalSrfSpeed) + "m/s" +
"\nLat: " + Tools.GetLatitudeString (vessel, "F3") + "\nLat: " + Tools.GetLatitudeString (vessel, "F3") +
" Lon: " + Tools.GetLongitudeString (vessel, "F3") + " Lon: " + Tools.GetLongitudeString (vessel, "F3") +
"\nHdg: " + Tools.MuMech_get_heading (vessel).ToString ("F2") + "° " + "\nHdg: " + Tools.MuMech_get_heading (vessel).ToString ("F2") + "° " +
Tools.get_heading_text (Tools.MuMech_get_heading (vessel)) + Tools.get_heading_text (Tools.MuMech_get_heading (vessel)) +
"\nBiome: " + Tools.Toadicus_GetAtt (vessel).name, "\nBiome: " + Tools.Toadicus_GetAtt (vessel).name +
  " Sit: " + vessel.GetExperimentSituation().HumanString(),
VOID_Core.Instance.LabelStyles["hud"]); VOID_Core.Instance.LabelStyles["hud"]);
} }
else else
{ {
VOID_Core.Instance.LabelStyles["hud"].normal.textColor = Color.red; VOID_Core.Instance.LabelStyles["hud"].normal.textColor = Color.red;
GUI.Label (new Rect ((Screen.width * .2083f), 0, 300f, 70f), "-- POWER LOST --", VOID_Core.Instance.LabelStyles["hud"]); GUI.Label (new Rect ((Screen.width * .2083f), 0, 300f, 70f), "-- POWER LOST --", VOID_Core.Instance.LabelStyles["hud"]);
GUI.Label (new Rect ((Screen.width * .625f), 0, 300f, 70f), "-- POWER LOST --", VOID_Core.Instance.LabelStyles["hud"]); GUI.Label (new Rect ((Screen.width * .625f), 0, 300f, 70f), "-- POWER LOST --", VOID_Core.Instance.LabelStyles["hud"]);
} }
} }
   
public override void DrawConfigurables() public override void DrawConfigurables()
{ {
if (GUILayout.Button ("Change HUD color", GUILayout.ExpandWidth (false))) if (GUILayout.Button ("Change HUD color", GUILayout.ExpandWidth (false)))
{ {
++this.ColorIndex; ++this.ColorIndex;
} }
} }
} }
} }
   
// //
// VOID_Orbital.cs // VOID_Orbital.cs
// //
// Author: // Author:
// toadicus <> // toadicus <>
// //
// Copyright (c) 2013 toadicus // Copyright (c) 2013 toadicus
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
using KSP; using KSP;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using UnityEngine; using UnityEngine;
   
namespace VOID namespace VOID
{ {
public class VOID_Rendezvous : VOID_WindowModule public class VOID_Rendezvous : VOID_WindowModule
{ {
[AVOID_SaveValue("untoggleRegisterInfo")] [AVOID_SaveValue("untoggleRegisterInfo")]
protected VOID_SaveValue<bool> untoggleRegisterInfo = false; protected VOID_SaveValue<bool> untoggleRegisterInfo = false;
   
[AVOID_SaveValue("toggleExtendedOrbital")] [AVOID_SaveValue("toggleExtendedOrbital")]
protected VOID_SaveValue<bool> toggleExtendedOrbital = false; protected VOID_SaveValue<bool> toggleExtendedOrbital = false;
   
protected VOID_VesselRegister RegisterModule; protected VOID_VesselRegister RegisterModule;
   
public VOID_Rendezvous() public VOID_Rendezvous()
{ {
this._Name = "Rendezvous Information"; this._Name = "Rendezvous Information";
   
this.WindowPos.x = 845; this.WindowPos.x = 845;
this.WindowPos.y = 85; this.WindowPos.y = 85;
} }
   
public override void ModuleWindow(int _) public override void ModuleWindow(int _)
{ {
Vessel rendezvessel = new Vessel(); Vessel rendezvessel = new Vessel();
CelestialBody rendezbody = new CelestialBody(); CelestialBody rendezbody = new CelestialBody();
   
this.RegisterModule = VOID_Core.Instance.Modules.Where(m => typeof(VOID_VesselRegister).IsAssignableFrom(m.GetType())).FirstOrDefault() as VOID_VesselRegister; this.RegisterModule = VOID_Core.Instance.Modules.Where(m => typeof(VOID_VesselRegister).IsAssignableFrom(m.GetType())).FirstOrDefault() as VOID_VesselRegister;
   
GUILayout.BeginVertical(); GUILayout.BeginVertical();
   
//display both //display both
//Show Target Info //Show Target Info
GUILayout.Label("Target:", VOID_Core.Instance.LabelStyles["center_bold"]); GUILayout.Label("Target:", VOID_Core.Instance.LabelStyles["center_bold"]);
if (FlightGlobals.fetch.VesselTarget != null) if (FlightGlobals.fetch.VesselTarget != null)
{ {
//a KSP Target (body or vessel) is selected //a KSP Target (body or vessel) is selected
if (FlightGlobals.fetch.vesselTargetMode == FlightGlobals.VesselTargetModes.Direction) if (FlightGlobals.fetch.vesselTargetMode == FlightGlobals.VesselTargetModes.Direction)
{ {
//a Body is selected //a Body is selected
rendezbody = vessel.patchedConicSolver.targetBody; rendezbody = vessel.patchedConicSolver.targetBody;
display_rendezvous_info(null, rendezbody); display_rendezvous_info(null, rendezbody);
} }
else if (FlightGlobals.fetch.vesselTargetMode == FlightGlobals.VesselTargetModes.DirectionAndVelocity) else if (FlightGlobals.fetch.vesselTargetMode == FlightGlobals.VesselTargetModes.DirectionAndVelocity)
{ {
//a Vessel is selected //a Vessel is selected
rendezvessel = FlightGlobals.fetch.VesselTarget.GetVessel(); rendezvessel = FlightGlobals.fetch.VesselTarget.GetVessel();
display_rendezvous_info(rendezvessel, null); display_rendezvous_info(rendezvessel, null);
} }
//Show Unset button for both options above //Show Unset button for both options above
if (GUILayout.Button("Unset Target", GUILayout.ExpandWidth(false))) if (GUILayout.Button("Unset Target", GUILayout.ExpandWidth(false)))
{ {
FlightGlobals.fetch.SetVesselTarget(null); FlightGlobals.fetch.SetVesselTarget(null);
Tools.PostDebugMessage("VOID_Rendezvous: KSP Target set to null"); Tools.PostDebugMessage("VOID_Rendezvous: KSP Target set to null");
} }
   
} }
else else
{ {
//no KSP Target selected //no KSP Target selected
GUILayout.Label("No Target Selected", VOID_Core.Instance.LabelStyles["center_bold"]); GUILayout.Label("No Target Selected", VOID_Core.Instance.LabelStyles["center_bold"]);
} }
   
//Show Vessel Register vessel info //Show Vessel Register vessel info
if (untoggleRegisterInfo == false && this.RegisterModule != default(IVOID_Module)) if (untoggleRegisterInfo == false && this.RegisterModule != default(IVOID_Module))
{ {
GUILayout.Label("Vessel Register:", VOID_Core.Instance.LabelStyles["center_bold"]); GUILayout.Label("Vessel Register:", VOID_Core.Instance.LabelStyles["center_bold"]);
if (this.RegisterModule.selectedVessel != null) if (this.RegisterModule.selectedVessel != null)
{ {
rendezvessel = this.RegisterModule.selectedVessel; rendezvessel = this.RegisterModule.selectedVessel;
display_rendezvous_info(rendezvessel, null); display_rendezvous_info(rendezvessel, null);
   
//show set/unset buttons //show set/unset buttons
if (FlightGlobals.fetch.VesselTarget == null || (FlightGlobals.fetch.VesselTarget != null && FlightGlobals.fetch.VesselTarget.GetVessel() != this.RegisterModule.selectedVessel)) if (FlightGlobals.fetch.VesselTarget == null || (FlightGlobals.fetch.VesselTarget != null && FlightGlobals.fetch.VesselTarget.GetVessel() != this.RegisterModule.selectedVessel))
{ {
//no Tgt set or Tgt is not this vessel //no Tgt set or Tgt is not this vessel
//show a Set button //show a Set button
if (GUILayout.Button("Set Target", GUILayout.ExpandWidth(false))) if (GUILayout.Button("Set Target", GUILayout.ExpandWidth(false)))
{ {
FlightGlobals.fetch.SetVesselTarget(rendezvessel); FlightGlobals.fetch.SetVesselTarget(rendezvessel);
Tools.PostDebugMessage("[VOID] KSP Target set to " + rendezvessel.vesselName); Tools.PostDebugMessage("[VOID] KSP Target set to " + rendezvessel.vesselName);
} }
} }
} }
else else
{ {
//vesreg Vessel is null //vesreg Vessel is null
//targ = null; //targ = null;
GUILayout.Label("No Vessel Selected", VOID_Core.Instance.LabelStyles["center_bold"]); GUILayout.Label("No Vessel Selected", VOID_Core.Instance.LabelStyles["center_bold"]);
} }
} }
   
untoggleRegisterInfo.value = GUILayout.Toggle(untoggleRegisterInfo, "Hide Vessel Register Info"); untoggleRegisterInfo.value = GUILayout.Toggle(untoggleRegisterInfo, "Hide Vessel Register Info");
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label(" ", GUILayout.ExpandWidth(true)); GUILayout.Label(" ", GUILayout.ExpandWidth(true));
if (GUILayout.Button("Close", GUILayout.ExpandWidth(false))) this._Active = false; if (GUILayout.Button("Close", GUILayout.ExpandWidth(false))) this._Active = false;
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.EndVertical(); GUILayout.EndVertical();
GUI.DragWindow(); GUI.DragWindow();
} }
   
private void display_rendezvous_info(Vessel v, CelestialBody cb) private void display_rendezvous_info(Vessel v, CelestialBody cb)
{ {
if (cb == null && v != null) if (cb == null && v != null)
{ {
//Display vessel rendezvous info //Display vessel rendezvous info
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label(v.vesselName, VOID_Core.Instance.LabelStyles["center_bold"], GUILayout.ExpandWidth(true)); GUILayout.Label(v.vesselName, VOID_Core.Instance.LabelStyles["center_bold"], GUILayout.ExpandWidth(true));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
if (v.situation == Vessel.Situations.ESCAPING || v.situation == Vessel.Situations.FLYING || v.situation == Vessel.Situations.ORBITING || v.situation == Vessel.Situations.SUB_ORBITAL) if (v.situation == Vessel.Situations.ESCAPING || v.situation == Vessel.Situations.FLYING || v.situation == Vessel.Situations.ORBITING || v.situation == Vessel.Situations.SUB_ORBITAL)
{ {
// Toadicus edit: added local sidereal longitude. // Toadicus edit: added local sidereal longitude.
// Toadicus edit: added local sidereal longitude. // Toadicus edit: added local sidereal longitude.
double LSL = vessel.longitude + vessel.orbit.referenceBody.rotationAngle; double LSL = v.longitude + v.orbit.referenceBody.rotationAngle;
LSL = Tools.FixDegreeDomain (LSL); LSL = Tools.FixDegreeDomain (LSL);
   
//display orbital info for orbiting/flying/suborbital/escaping vessels only //display orbital info for orbiting/flying/suborbital/escaping vessels only
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Ap/Pe:"); GUILayout.Label("Ap/Pe:");
GUILayout.Label(Tools.MuMech_ToSI(v.orbit.ApA) + "m / " + Tools.MuMech_ToSI(v.orbit.PeA) + "m", GUILayout.ExpandWidth(false)); GUILayout.Label(Tools.MuMech_ToSI(v.orbit.ApA) + "m / " + Tools.MuMech_ToSI(v.orbit.PeA) + "m", GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Altitude:"); GUILayout.Label("Altitude:");
GUILayout.Label(Tools.MuMech_ToSI(v.orbit.altitude) + "m", GUILayout.ExpandWidth(false)); GUILayout.Label(Tools.MuMech_ToSI(v.orbit.altitude) + "m", GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Inclination:"); GUILayout.Label("Inclination:");
GUILayout.Label(v.orbit.inclination.ToString("F3") + "°", GUILayout.ExpandWidth(false)); GUILayout.Label(v.orbit.inclination.ToString("F3") + "°", GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
if (vessel.mainBody == v.mainBody) if (vessel.mainBody == v.mainBody)
{ {
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Relative inclination:"); GUILayout.Label("Relative inclination:");
GUILayout.Label(Vector3d.Angle(vessel.orbit.GetOrbitNormal(), v.orbit.GetOrbitNormal()).ToString("F3") + "°", GUILayout.ExpandWidth(false)); GUILayout.Label(Vector3d.Angle(vessel.orbit.GetOrbitNormal(), v.orbit.GetOrbitNormal()).ToString("F3") + "°", GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
//if (debugging) Debug.Log("[CHATR] v -> v relative incl OK"); //if (debugging) Debug.Log("[CHATR] v -> v relative incl OK");
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Velocity:"); GUILayout.Label("Velocity:");
GUILayout.Label(Tools.MuMech_ToSI(v.orbit.vel.magnitude) + "m/s", GUILayout.ExpandWidth(false)); GUILayout.Label(Tools.MuMech_ToSI(v.orbit.vel.magnitude) + "m/s", GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Relative velocity:"); GUILayout.Label("Relative velocity:");
GUILayout.Label(Tools.MuMech_ToSI(v.orbit.vel.magnitude - vessel.orbit.vel.magnitude) + "m/s", GUILayout.ExpandWidth(false)); GUILayout.Label(Tools.MuMech_ToSI(v.orbit.vel.magnitude - vessel.orbit.vel.magnitude) + "m/s", GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Distance:"); GUILayout.Label("Distance:");
GUILayout.Label(Tools.MuMech_ToSI((vessel.findWorldCenterOfMass() - v.findWorldCenterOfMass()).magnitude) + "m", GUILayout.ExpandWidth(false)); GUILayout.Label(Tools.MuMech_ToSI((vessel.findWorldCenterOfMass() - v.findWorldCenterOfMass()).magnitude) + "m", GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
//target_vessel_extended_orbital_info = GUILayout.Toggle(target_vessel_extended_orbital_info, "Extended info"); //target_vessel_extended_orbital_info = GUILayout.Toggle(target_vessel_extended_orbital_info, "Extended info");
   
if (toggleExtendedOrbital) if (toggleExtendedOrbital)
{ {
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Period:"); GUILayout.Label("Period:");
GUILayout.Label(Tools.ConvertInterval(v.orbit.period), GUILayout.ExpandWidth(false)); GUILayout.Label(Tools.ConvertInterval(v.orbit.period), GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Semi-major axis:"); GUILayout.Label("Semi-major axis:");
GUILayout.Label((v.orbit.semiMajorAxis / 1000).ToString("##,#") + "km", GUILayout.ExpandWidth(false)); GUILayout.Label((v.orbit.semiMajorAxis / 1000).ToString("##,#") + "km", GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Eccentricity:"); GUILayout.Label("Eccentricity:");
GUILayout.Label(v.orbit.eccentricity.ToString("F4"), GUILayout.ExpandWidth(false)); GUILayout.Label(v.orbit.eccentricity.ToString("F4"), GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
// Toadicus edit: convert mean anomaly into degrees. // Toadicus edit: convert mean anomaly into degrees.
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Mean anomaly:"); GUILayout.Label("Mean anomaly:");
GUILayout.Label((v.orbit.meanAnomaly * 180d / Math.PI).ToString("F3") + "°", GUILayout.ExpandWidth(false)); GUILayout.Label((v.orbit.meanAnomaly * 180d / Math.PI).ToString("F3") + "°", GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("True anomaly:"); GUILayout.Label("True anomaly:");
GUILayout.Label(v.orbit.trueAnomaly.ToString("F3") + "°", GUILayout.ExpandWidth(false)); GUILayout.Label(v.orbit.trueAnomaly.ToString("F3") + "°", GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
// Toadicus edit: convert eccentric anomaly into degrees. // Toadicus edit: convert eccentric anomaly into degrees.
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Eccentric anomaly:"); GUILayout.Label("Eccentric anomaly:");
GUILayout.Label((v.orbit.eccentricAnomaly * 180d / Math.PI).ToString("F3") + "°", GUILayout.ExpandWidth(false)); GUILayout.Label((v.orbit.eccentricAnomaly * 180d / Math.PI).ToString("F3") + "°", GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Long. ascending node:"); GUILayout.Label("Long. ascending node:");
GUILayout.Label(v.orbit.LAN.ToString("F3") + "°", GUILayout.ExpandWidth(false)); GUILayout.Label(v.orbit.LAN.ToString("F3") + "°", GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Arg. of periapsis:"); GUILayout.Label("Arg. of periapsis:");
GUILayout.Label(v.orbit.argumentOfPeriapsis.ToString("F3") + "°", GUILayout.ExpandWidth(false)); GUILayout.Label(v.orbit.argumentOfPeriapsis.ToString("F3") + "°", GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
// Toadicus edit: added local sidereal longitude. // Toadicus edit: added local sidereal longitude.
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Local Sidereal Longitude:"); GUILayout.Label("Local Sidereal Longitude:");
GUILayout.Label(LSL.ToString("F3") + "°", VOID_Core.Instance.LabelStyles["right"]); GUILayout.Label(LSL.ToString("F3") + "°", VOID_Core.Instance.LabelStyles["right"]);
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
} }
else else
{ {
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Latitude:"); GUILayout.Label("Latitude:");
GUILayout.Label(Tools.GetLatitudeString(vessel), GUILayout.ExpandWidth(false)); GUILayout.Label(Tools.GetLatitudeString(vessel), GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Longitude:"); GUILayout.Label("Longitude:");
GUILayout.Label(Tools.GetLongitudeString(vessel), GUILayout.ExpandWidth(false)); GUILayout.Label(Tools.GetLongitudeString(vessel), GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Distance:"); GUILayout.Label("Distance:");
GUILayout.Label(Tools.MuMech_ToSI((vessel.findWorldCenterOfMass() - v.findWorldCenterOfMass()).magnitude) + "m", GUILayout.ExpandWidth(false)); GUILayout.Label(Tools.MuMech_ToSI((vessel.findWorldCenterOfMass() - v.findWorldCenterOfMass()).magnitude) + "m", GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
} }
else if (cb != null && v == null) else if (cb != null && v == null)
{ {
//Display CelstialBody rendezvous info //Display CelstialBody rendezvous info
GUILayout.Label(cb.bodyName, VOID_Core.Instance.LabelStyles["center_bold"]); GUILayout.Label(cb.bodyName, VOID_Core.Instance.LabelStyles["center_bold"]);
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Ap/Pe:"); GUILayout.Label("Ap/Pe:");
GUILayout.Label(Tools.MuMech_ToSI(cb.orbit.ApA) + "m / " + Tools.MuMech_ToSI(cb.orbit.PeA) + "m", GUILayout.ExpandWidth(false)); GUILayout.Label(Tools.MuMech_ToSI(cb.orbit.ApA) + "m / " + Tools.MuMech_ToSI(cb.orbit.PeA) + "m", GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
//if (debugging) Debug.Log("[VOID] Ap/Pe OK"); //if (debugging) Debug.Log("[VOID] Ap/Pe OK");
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Inclination:"); GUILayout.Label("Inclination:");
GUILayout.Label(cb.orbit.inclination.ToString("F3") + "°", GUILayout.ExpandWidth(false)); GUILayout.Label(cb.orbit.inclination.ToString("F3") + "°", GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
//if (debugging) Debug.Log("[VOID] Inclination OK"); //if (debugging) Debug.Log("[VOID] Inclination OK");
   
if (cb.referenceBody == vessel.mainBody) if (cb.referenceBody == vessel.mainBody)
{ {
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Relative inclination:"); GUILayout.Label("Relative inclination:");
GUILayout.Label(Vector3d.Angle(vessel.orbit.GetOrbitNormal(), cb.orbit.GetOrbitNormal()).ToString("F3") + "°", GUILayout.ExpandWidth(false)); GUILayout.Label(Vector3d.Angle(vessel.orbit.GetOrbitNormal(), cb.orbit.GetOrbitNormal()).ToString("F3") + "°", GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
//if (debugging) Debug.Log("[VOID] cb Relative inclination OK"); //if (debugging) Debug.Log("[VOID] cb Relative inclination OK");
} }
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Distance:"); GUILayout.Label("Distance:");
GUILayout.Label(Tools.MuMech_ToSI((vessel.mainBody.position - cb.position).magnitude) + "m", GUILayout.ExpandWidth(false)); GUILayout.Label(Tools.MuMech_ToSI((vessel.mainBody.position - cb.position).magnitude) + "m", GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
//if (debugging) Debug.Log("[VOID] Distance OK"); //if (debugging) Debug.Log("[VOID] Distance OK");
   
//SUN2PLANET: //SUN2PLANET:
if (vessel.mainBody.bodyName == "Sun" && cb.referenceBody == vessel.mainBody) if (vessel.mainBody.bodyName == "Sun" && cb.referenceBody == vessel.mainBody)
{ {
Tools.display_transfer_angles_SUN2PLANET(cb, vessel); Tools.display_transfer_angles_SUN2PLANET(cb, vessel);
//if (debugging) Debug.Log("[VOID] SUN2PLANET OK"); //if (debugging) Debug.Log("[VOID] SUN2PLANET OK");
} }
   
//PLANET2PLANET //PLANET2PLANET
else if (vessel.mainBody.referenceBody.bodyName == "Sun" && cb.referenceBody == vessel.mainBody.referenceBody) else if (vessel.mainBody.referenceBody.bodyName == "Sun" && cb.referenceBody == vessel.mainBody.referenceBody)
{ {
Tools.display_transfer_angles_PLANET2PLANET(cb, vessel); Tools.display_transfer_angles_PLANET2PLANET(cb, vessel);
//if (debugging) Debug.Log("[VOID] PLANET2PLANET OK"); //if (debugging) Debug.Log("[VOID] PLANET2PLANET OK");
} }
   
//PLANET2MOON //PLANET2MOON
else if (vessel.mainBody.referenceBody.bodyName == "Sun" && cb.referenceBody == vessel.mainBody) else if (vessel.mainBody.referenceBody.bodyName == "Sun" && cb.referenceBody == vessel.mainBody)
{ {
Tools.display_transfer_angles_PLANET2MOON(cb, vessel); Tools.display_transfer_angles_PLANET2MOON(cb, vessel);
//if (debugging) Debug.Log("[VOID] PLANET2MOON OK"); //if (debugging) Debug.Log("[VOID] PLANET2MOON OK");
} }
   
//MOON2MOON //MOON2MOON
else if (vessel.mainBody.referenceBody.referenceBody.bodyName == "Sun" && cb.referenceBody == vessel.mainBody.referenceBody) else if (vessel.mainBody.referenceBody.referenceBody.bodyName == "Sun" && cb.referenceBody == vessel.mainBody.referenceBody)
{ {
Tools.display_transfer_angles_MOON2MOON(cb, vessel); Tools.display_transfer_angles_MOON2MOON(cb, vessel);
//if (debugging) Debug.Log("[VOID] MOON2MOON OK"); //if (debugging) Debug.Log("[VOID] MOON2MOON OK");
} }
   
//else GUILayout.Label("Transfer angle information\nunavailable for this target"); //else GUILayout.Label("Transfer angle information\nunavailable for this target");
   
} }
} }
} }
} }
// //
// VOID_Orbital.cs // VOID_Orbital.cs
// //
// Author: // Author:
// toadicus <> // toadicus <>
// //
// Copyright (c) 2013 toadicus // Copyright (c) 2013 toadicus
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
using KSP; using KSP;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
using Engineer.VesselSimulator; using Engineer.VesselSimulator;
  using Engineer.Extensions;
   
namespace VOID namespace VOID
{ {
public class VOID_VesselInfo : VOID_WindowModule public class VOID_VesselInfo : VOID_WindowModule
{ {
protected VOID_DoubleValue geeForce = new VOID_DoubleValue( protected VOID_DoubleValue geeForce = new VOID_DoubleValue(
"G-force", "G-force",
new Func<double>(() => VOID_Core.Instance.vessel.geeForce), new Func<double>(() => VOID_Core.Instance.vessel.geeForce),
"gees" "gees"
); );
   
protected VOID_IntValue partCount = new VOID_IntValue( protected VOID_IntValue partCount = new VOID_IntValue(
"Parts", "Parts",
new Func<int>(() => VOID_Core.Instance.vessel.Parts.Count), new Func<int>(() => VOID_Core.Instance.vessel.Parts.Count),
"" ""
); );
   
protected VOID_DoubleValue totalMass = new VOID_DoubleValue( protected VOID_DoubleValue totalMass = new VOID_DoubleValue(
"Total Mass", "Total Mass",
new Func<double>(() => VOID_Core.Instance.vessel.GetTotalMass()), new Func<double>(() => VOID_Core.Instance.vessel.GetTotalMass()),
"tons" "tons"
); );
   
protected VOID_DoubleValue resourceMass = new VOID_DoubleValue( protected VOID_DoubleValue resourceMass = new VOID_DoubleValue(
"Resource Mass", "Resource Mass",
delegate() delegate()
{ {
double rscMass = 0; double rscMass = 0;
foreach (Part part in VOID_Core.Instance.vessel.Parts) foreach (Part part in VOID_Core.Instance.vessel.Parts)
{ {
rscMass += part.GetResourceMass(); rscMass += part.GetResourceMass();
} }
return rscMass; return rscMass;
}, },
"tons" "tons"
); );
   
protected VOID_DoubleValue stageDeltaV = new VOID_DoubleValue( protected VOID_DoubleValue stageDeltaV = new VOID_DoubleValue(
"DeltaV (Current Stage)", "DeltaV (Current Stage)",
delegate() delegate()
{ {
if (SimManager.Instance.Stages == null || if (SimManager.Instance.Stages == null ||
SimManager.Instance.Stages.Length <= Staging.lastStage SimManager.Instance.Stages.Length <= Staging.lastStage
) )
return double.NaN; return double.NaN;
return SimManager.Instance.Stages[Staging.lastStage].deltaV; return SimManager.Instance.Stages[Staging.lastStage].deltaV;
}, },
"m/s" "m/s"
); );
   
protected VOID_DoubleValue totalDeltaV = new VOID_DoubleValue( protected VOID_DoubleValue totalDeltaV = new VOID_DoubleValue(
"DeltaV (Total)", "DeltaV (Total)",
delegate() delegate()
{ {
if (SimManager.Instance.Stages == null) if (SimManager.Instance.Stages == null)
return double.NaN; return double.NaN;
return SimManager.Instance.LastStage.totalDeltaV; return SimManager.Instance.LastStage.totalDeltaV;
}, },
"m/s" "m/s"
); );
   
protected VOID_FloatValue mainThrottle = new VOID_FloatValue( protected VOID_FloatValue mainThrottle = new VOID_FloatValue(
"Throttle", "Throttle",
new Func<float>(() => VOID_Core.Instance.vessel.ctrlState.mainThrottle * 100f), new Func<float>(() => VOID_Core.Instance.vessel.ctrlState.mainThrottle * 100f),
"%" "%"
); );
   
protected VOID_StrValue currmaxThrust = new VOID_StrValue( protected VOID_StrValue currmaxThrust = new VOID_StrValue(
"Thrust (curr/max)", "Thrust (curr/max)",
delegate() delegate()
{ {
if (SimManager.Instance.Stages == null) if (SimManager.Instance.Stages == null)
return "N/A"; return "N/A";
   
double currThrust = SimManager.Instance.LastStage.actualThrust; double currThrust = SimManager.Instance.LastStage.actualThrust;
double maxThrust = SimManager.Instance.LastStage.thrust; double maxThrust = SimManager.Instance.LastStage.thrust;
   
return string.Format( return string.Format(
"{0} / {1}", "{0} / {1}",
currThrust.ToString("F1"), currThrust.ToString("F1"),
maxThrust.ToString("F1") maxThrust.ToString("F1")
); );
} }
); );
   
protected VOID_StrValue currmaxThrustWeight = new VOID_StrValue( protected VOID_StrValue currmaxThrustWeight = new VOID_StrValue(
"T:W (curr/max)", "T:W (curr/max)",
delegate() delegate()
{ {
if (SimManager.Instance.Stages == null) if (SimManager.Instance.Stages == null)
return "N/A"; return "N/A";
   
double currThrust = SimManager.Instance.LastStage.actualThrust; double currThrust = SimManager.Instance.LastStage.actualThrust;
double maxThrust = SimManager.Instance.LastStage.thrust; double maxThrust = SimManager.Instance.LastStage.thrust;
double mass = VOID_Core.Instance.vessel.GetTotalMass(); double mass = VOID_Core.Instance.vessel.GetTotalMass();
double gravity = VOID_Core.Instance.vessel.mainBody.gravParameter / double gravity = VOID_Core.Instance.vessel.mainBody.gravParameter /
Math.Pow( Math.Pow(
VOID_Core.Instance.vessel.mainBody.Radius + VOID_Core.Instance.vessel.altitude, VOID_Core.Instance.vessel.mainBody.Radius + VOID_Core.Instance.vessel.altitude,
2 2
); );
double weight = mass * gravity; double weight = mass * gravity;
   
return string.Format( return string.Format(
"{0} / {1}", "{0} / {1}",
(currThrust / weight).ToString("F2"), (currThrust / weight).ToString("F2"),
(maxThrust / weight).ToString("F2") (maxThrust / weight).ToString("F2")
); );
} }
); );
   
protected VOID_DoubleValue surfaceThrustWeight = new VOID_DoubleValue( protected VOID_DoubleValue surfaceThrustWeight = new VOID_DoubleValue(
"Max T:W @ surface", "Max T:W @ surface",
delegate() delegate()
{ {
if (SimManager.Instance.Stages == null) if (SimManager.Instance.Stages == null)
return double.NaN; return double.NaN;
   
double maxThrust = SimManager.Instance.LastStage.thrust; double maxThrust = SimManager.Instance.LastStage.thrust;
double mass = VOID_Core.Instance.vessel.GetTotalMass(); double mass = VOID_Core.Instance.vessel.GetTotalMass();
double gravity = (VOID_Core.Constant_G * VOID_Core.Instance.vessel.mainBody.Mass) / double gravity = (VOID_Core.Constant_G * VOID_Core.Instance.vessel.mainBody.Mass) /
Math.Pow(VOID_Core.Instance.vessel.mainBody.Radius, 2); Math.Pow(VOID_Core.Instance.vessel.mainBody.Radius, 2);
double weight = mass * gravity; double weight = mass * gravity;
   
return maxThrust / weight; return maxThrust / weight;
}, },
"" ""
); );
   
  protected VOID_StrValue intakeAirStatus = new VOID_StrValue(
  "Intake Air (Curr / Req)",
  delegate()
  {
  double currentAmount;
  double currentRequirement;
   
  currentAmount = 0d;
  currentRequirement = 0d;
   
  foreach (Part part in VOID_Core.Instance.vessel.Parts)
  {
  if (part.HasModule<ModuleEngines>() && part.enabled)
  {
  foreach (Propellant propellant in part.GetModule<ModuleEngines>().propellants)
  {
  if (propellant.name == "IntakeAir")
  {
  // currentAmount += propellant.currentAmount;
  currentRequirement += propellant.currentRequirement / TimeWarp.fixedDeltaTime;
  break;
  }
  }
  }
   
  if (part.HasModule<ModuleResourceIntake>() && part.enabled)
  {
  ModuleResourceIntake intakeModule = part.GetModule<ModuleResourceIntake>();
   
  if (intakeModule.resourceName == "IntakeAir")
  {
  currentAmount += intakeModule.airFlow;
  }
  }
  }
   
  if (currentAmount == 0 && currentRequirement == 0)
  {
  return "N/A";
  }
   
  return string.Format("{0:F3} / {1:F3}", currentAmount, currentRequirement);
  }
  );
   
public VOID_VesselInfo() : base() public VOID_VesselInfo() : base()
{ {
this._Name = "Vessel Information"; this._Name = "Vessel Information";
   
this.WindowPos.x = Screen.width - 260; this.WindowPos.x = Screen.width - 260;
this.WindowPos.y = 450; this.WindowPos.y = 450;
} }
   
public override void ModuleWindow(int _) public override void ModuleWindow(int _)
{ {
base.ModuleWindow (_); base.ModuleWindow (_);
   
if ((TimeWarp.WarpMode == TimeWarp.Modes.LOW) || (TimeWarp.CurrentRate <= TimeWarp.MaxPhysicsRate)) if ((TimeWarp.WarpMode == TimeWarp.Modes.LOW) || (TimeWarp.CurrentRate <= TimeWarp.MaxPhysicsRate))
{ {
SimManager.Instance.RequestSimulation(); SimManager.Instance.RequestSimulation();
} }
   
Stage[] stages = SimManager.Instance.Stages; Stage[] stages = SimManager.Instance.Stages;
   
GUILayout.BeginVertical(); GUILayout.BeginVertical();
   
GUILayout.Label( GUILayout.Label(
vessel.vesselName, vessel.vesselName,
VOID_Core.Instance.LabelStyles["center_bold"], VOID_Core.Instance.LabelStyles["center_bold"],
GUILayout.ExpandWidth(true)); GUILayout.ExpandWidth(true));
   
this.geeForce.DoGUIHorizontal ("F2"); this.geeForce.DoGUIHorizontal ("F2");
   
this.partCount.DoGUIHorizontal (); this.partCount.DoGUIHorizontal ();
   
this.totalMass.DoGUIHorizontal ("F1"); this.totalMass.DoGUIHorizontal ("F1");
   
this.resourceMass.DoGUIHorizontal ("F1"); this.resourceMass.DoGUIHorizontal ("F1");
   
this.stageDeltaV.DoGUIHorizontal (3, false); this.stageDeltaV.DoGUIHorizontal (3, false);
   
this.totalDeltaV.DoGUIHorizontal (3, false); this.totalDeltaV.DoGUIHorizontal (3, false);
   
this.mainThrottle.DoGUIHorizontal ("F0"); this.mainThrottle.DoGUIHorizontal ("F0");
   
this.currmaxThrust.DoGUIHorizontal (); this.currmaxThrust.DoGUIHorizontal ();
   
this.currmaxThrustWeight.DoGUIHorizontal (); this.currmaxThrustWeight.DoGUIHorizontal ();
   
this.surfaceThrustWeight.DoGUIHorizontal ("F2"); this.surfaceThrustWeight.DoGUIHorizontal ("F2");
   
  this.intakeAirStatus.DoGUIHorizontal();
   
GUILayout.EndVertical(); GUILayout.EndVertical();
GUI.DragWindow(); GUI.DragWindow();
} }
} }
} }