VOID_Core: Moved LabelStyles initializers into their own, run-once function.
VOID_Core: Moved LabelStyles initializers into their own, run-once function.

file:a/AVOID_ConfigValue.cs (deleted)
//  
// AVOID_ConfigValue.cs  
//  
// Author:  
// toadicus <>  
//  
// Copyright (c) 2013 toadicus  
//  
// This program is free software: you can redistribute it and/or modify  
// it under the terms of the GNU General Public License as published by  
// the Free Software Foundation, either version 3 of the License, or  
// (at your option) any later version.  
//  
// This program is distributed in the hope that it will be useful,  
// but WITHOUT ANY WARRANTY; without even the implied warranty of  
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the  
// GNU General Public License for more details.  
//  
// You should have received a copy of the GNU General Public License  
// along with this program. If not, see <http://www.gnu.org/licenses/>.  
using System;  
 
namespace VOID  
{  
 
}  
 
 
file:a/AVOID_Configurable.cs (deleted)
//  
// AVOID_Configurable.cs  
//  
// Author:  
// toadicus <>  
//  
// Copyright (c) 2013 toadicus  
//  
// This program is free software: you can redistribute it and/or modify  
// it under the terms of the GNU General Public License as published by  
// the Free Software Foundation, either version 3 of the License, or  
// (at your option) any later version.  
//  
// This program is distributed in the hope that it will be useful,  
// but WITHOUT ANY WARRANTY; without even the implied warranty of  
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the  
// GNU General Public License for more details.  
//  
// You should have received a copy of the GNU General Public License  
// along with this program. If not, see <http://www.gnu.org/licenses/>.  
using System;  
 
namespace VOID  
{  
[AttributeUsage(AttributeTargets.Method)]  
public class AVOID_Configurable : Attribute { }  
}  
 
 
// //
// IVOID_Module.cs // IVOID_Module.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;
   
namespace VOID namespace VOID
{ {
public interface IVOID_Module public interface IVOID_Module
{ {
string Name { get; } string Name { get; }
bool hasConfigurables { get; }  
bool toggleActive { get; set; } bool toggleActive { get; set; }
bool guiRunning { get; } bool guiRunning { get; }
   
void DrawGUI(); void DrawGUI();
void StartGUI(); void StartGUI();
void StopGUI(); void StopGUI();
   
void DrawConfigurables(); void DrawConfigurables();
   
void LoadConfig(); void LoadConfig();
   
void SaveConfig(); void SaveConfig();
} }
} }
   
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 class VOIDLabels public static class VOIDLabels
{ {
public string void_primary; public static string void_primary = "Primary";
public string void_altitude_asl; public static string void_altitude_asl = "Altitude (ASL)";
public string void_velocity; public static string void_velocity = "Velocity";
public string void_apoapsis; public static string void_apoapsis = "Apoapsis";
public string void_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;
   
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 = vessel.findWorldCenterOfMass();
Vector3d up = (CoM - vessel.mainBody.position).normalized; Vector3d up = (CoM - vessel.mainBody.position).normalized;
Vector3d north = Vector3d.Exclude(up, (vessel.mainBody.position + vessel.mainBody.transform.up * (float)vessel.mainBody.Radius) - CoM).normalized; Vector3d north = Vector3d.Exclude(up, (vessel.mainBody.position + vessel.mainBody.transform.up * (float)vessel.mainBody.Radius) - CoM).normalized;
   
Quaternion rotationSurface = Quaternion.LookRotation(north, up); Quaternion rotationSurface = Quaternion.LookRotation(north, up);
Quaternion rotationvesselSurface = Quaternion.Inverse(Quaternion.Euler(90, 0, 0) * Quaternion.Inverse(vessel.transform.rotation) * rotationSurface); Quaternion rotationvesselSurface = Quaternion.Inverse(Quaternion.Euler(90, 0, 0) * Quaternion.Inverse(vessel.transform.rotation) * rotationSurface);
MuMech_MovingAverage vesselHeading = new MuMech_MovingAverage(); MuMech_MovingAverage vesselHeading = new MuMech_MovingAverage();
vesselHeading.value = rotationvesselSurface.eulerAngles.y; vesselHeading.value = rotationvesselSurface.eulerAngles.y;
return vesselHeading.value * 10; // *10 by me return vesselHeading.value * 10; // *10 by me
} }
   
//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(double d) public static string MuMech_ToSI(double d)
{ {
int digits = 2; int digits = 2;
double exponent = Math.Log10(Math.Abs(d)); double exponent = Math.Log10(Math.Abs(d));
if (Math.Abs(d) >= 1) if (Math.Abs(d) >= 1)
{ {
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 (Math.Abs(d) > 0) else if (Math.Abs(d) > 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) angle = angle - 1;
if (angle < 0) angle = angle + 1; if (angle < 0) angle = angle + 1;
if (angle > 0.5) 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) eangle = eangle + 360;
while (eangle > 360) eangle = eangle - 360; while (eangle > 360) eangle = eangle - 360;
if (eangle < 270) eangle = 90 - eangle; if (eangle < 270) eangle = 90 - eangle;
else eangle = 450 - 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) return (-1 * (360 - curr_phase));
else if (curr_phase < 0) return 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) return curr_phase;
else if (curr_phase < 0) return (360 + 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) return 360 + curr_ejection;
else return 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) return 180 + trans_ejection;
else return 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, and water covers the whole surface 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.
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) return "N";
else if (heading > 11.25 && heading <= 33.75) return "NNE"; else if (heading > 11.25 && heading <= 33.75) return "NNE";
else if (heading > 33.75 && heading <= 56.25) return "NE"; else if (heading > 33.75 && heading <= 56.25) return "NE";
else if (heading > 56.25 && heading <= 78.75) return "ENE"; else if (heading > 56.25 && heading <= 78.75) return "ENE";
else if (heading > 78.75 && heading <= 101.25) return "E"; else if (heading > 78.75 && heading <= 101.25) return "E";
else if (heading > 101.25 && heading <= 123.75) return "ESE"; else if (heading > 101.25 && heading <= 123.75) return "ESE";
else if (heading > 123.75 && heading <= 146.25) return "SE"; else if (heading > 123.75 && heading <= 146.25) return "SE";
else if (heading > 146.25 && heading <= 168.75) return "SSE"; else if (heading > 146.25 && heading <= 168.75) return "SSE";
else if (heading > 168.75 && heading <= 191.25) return "S"; else if (heading > 168.75 && heading <= 191.25) return "S";
else if (heading > 191.25 && heading <= 213.75) return "SSW"; else if (heading > 191.25 && heading <= 213.75) return "SSW";
else if (heading > 213.75 && heading <= 236.25) return "SW"; else if (heading > 213.75 && heading <= 236.25) return "SW";
else if (heading > 236.25 && heading <= 258.75) return "WSW"; else if (heading > 236.25 && heading <= 258.75) return "WSW";
else if (heading > 258.75 && heading <= 281.25) return "W"; else if (heading > 258.75 && heading <= 281.25) return "W";
else if (heading > 281.25 && heading <= 303.75) return "WNW"; else if (heading > 281.25 && heading <= 303.75) return "WNW";
else if (heading > 303.75 && heading <= 326.25) return "NW"; else if (heading > 303.75 && heading <= 326.25) return "NW";
else if (heading > 326.25 && heading <= 348.75) return "NNW"; else if (heading > 326.25 && heading <= 348.75) return "NNW";
else return ""; else return "";
} }
   
public static double[] ParseXYString(string s) public static double[] ParseXYString(string s)
{ {
string[] xy = s.Split (','); string[] xy = s.Split (',');
if (xy.Length != 2) if (xy.Length != 2)
{ {
throw new ArgumentException ("Argument must be of the format 'x,y'."); throw new ArgumentException ("Argument must be of the format 'x,y'.");
} }
   
double x = double.Parse (xy [0].Trim ()); double x = double.Parse (xy [0].Trim ());
double y = double.Parse (xy [1].Trim ()); double y = double.Parse (xy [1].Trim ());
   
return new double[] { x, y }; return new double[] { x, y };
} }
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_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 System.Reflection; using System.Reflection;
using KSP; using KSP;
using UnityEngine; using UnityEngine;
   
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 double Constant_G = 6.674e-11;
   
/* /*
* Fields * Fields
* */ * */
protected string VoidName = "VOID"; protected string VoidName = "VOID";
protected string VoidVersion = "0.9.9"; protected string VoidVersion = "0.9.9";
   
[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;
   
protected List<Callback> _configurableCallbacks = new List<Callback>(); protected List<Callback> _configurableCallbacks = new List<Callback>();
   
[AVOID_SaveValue("mainWindowPos")] [AVOID_SaveValue("mainWindowPos")]
protected VOID_SaveValue<Rect> mainWindowPos = new Rect(Screen.width / 2, Screen.height / 2, 10f, 10f); protected VOID_SaveValue<Rect> mainWindowPos = new Rect(Screen.width / 2, Screen.height / 2, 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(Screen.width / 2, Screen.height /2, 10f, 10f); protected VOID_SaveValue<Rect> configWindowPos = new Rect(Screen.width / 2, Screen.height /2, 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 - 30, 30f, 30f);
protected Texture2D VOIDIconOff = new Texture2D(30, 30, TextureFormat.ARGB32, false); protected Texture2D VOIDIconOff = new Texture2D(30, 30, TextureFormat.ARGB32, false);
protected Texture2D VOIDIconOn = new Texture2D(30, 30, TextureFormat.ARGB32, false); protected Texture2D VOIDIconOn = new Texture2D(30, 30, TextureFormat.ARGB32, false);
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 int windowBaseID = -96518722; protected int windowBaseID = -96518722;
  protected int _windowID = 0;
   
  protected bool GUIStylesLoaded = false;
   
  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;
   
public float saveTimer = 0; public float saveTimer = 0;
   
protected string defaultSkin = "KSP window 2"; protected string defaultSkin = "KSP window 2";
protected VOID_SaveValue<string> _skin; protected VOID_SaveValue<string> _skin;
   
public bool configDirty; public bool configDirty;
   
/* /*
* Properties * Properties
* */ * */
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._skin == null) if (this._skin == null)
{ {
this._skin = this.defaultSkin; this._skin = this.defaultSkin;
} }
return AssetBase.GetGUISkin(this._skin); return AssetBase.GetGUISkin(this._skin);
} }
} }
   
public Vessel vessel public int windowID
{ {
get get
{ {
return FlightGlobals.ActiveVessel; if (this._windowID == 0)
  {
  this._windowID = this.windowBaseID;
  }
  return this._windowID++;
  }
  }
   
  public Dictionary<string, GUIStyle> LabelStyles
  {
  get
  {
  return this._LabelStyles;
} }
} }
   
/* /*
* Methods * Methods
* */ * */
protected VOID_Core() protected VOID_Core()
{ {
this._Name = "VOID Core"; this._Name = "VOID Core";
   
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);
   
Tools.PostDebugMessage (string.Format ("VOID_Core: Loaded {0} modules.", this.Modules.Count));  
   
this.LoadConfig (); this.LoadConfig ();
} }
   
protected void LoadModules() protected void LoadModules()
{ {
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(IVOID_Module).IsAssignableFrom (v) .Where (v => typeof(IVOID_Module).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}: Checking {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) foreach (var voidType in types)
{ {
Tools.PostDebugMessage (string.Format ( Tools.PostDebugMessage (string.Format (
"{0}: found Type {1}", "{0}: found Type {1}",
this.GetType ().Name, this.GetType ().Name,
voidType.Name voidType.Name
)); ));
   
this.LoadModule(voidType); this.LoadModule(voidType);
} }
   
this._modulesLoaded = true; this._modulesLoaded = true;
   
  Tools.PostDebugMessage (string.Format ("VOID_Core: Loaded {0} modules.", 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();
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
)); ));
} }
   
public void Update() public void Update()
{ {
this.saveTimer += Time.deltaTime; this.saveTimer += Time.deltaTime;
   
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 || !this.togglePower || !HighLogic.LoadedSceneIsFlight) if (module.guiRunning && !module.toggleActive || !this.togglePower || !HighLogic.LoadedSceneIsFlight)
{ {
module.StopGUI(); module.StopGUI();
} }
} }
   
if (this.saveTimer > 15f) if (this.saveTimer > 15f)
{ {
this.SaveConfig (); this.SaveConfig ();
this.saveTimer = 0; this.saveTimer = 0;
} }
} }
   
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;
} }
} }
  }
   
  protected void LoadGUIStyles()
  {
  this.LabelStyles["center"] = new GUIStyle(GUI.skin.label);
  this.LabelStyles["center"].normal.textColor = Color.white;
  this.LabelStyles["center"].alignment = TextAnchor.UpperCenter;
   
  this.LabelStyles["center_bold"] = new GUIStyle(GUI.skin.label);
  this.LabelStyles["center_bold"].normal.textColor = Color.white;
  this.LabelStyles["center_bold"].alignment = TextAnchor.UpperCenter;
  this.LabelStyles["center_bold"].fontStyle = FontStyle.Bold;
   
  this.LabelStyles["txt_right"] = new GUIStyle(GUI.skin.label);
  this.LabelStyles["txt_right"].normal.textColor = Color.white;
  this.LabelStyles["txt_right"].alignment = TextAnchor.UpperRight;
   
  this.GUIStylesLoaded = true;
} }
   
public void VOIDMainWindow(int _) public void VOIDMainWindow(int _)
{ {
GUILayout.BeginVertical(); GUILayout.BeginVertical();
if (this.powerAvailable) if (this.powerAvailable)
{ {
string str = "ON"; string str = "ON";
if (togglePower) str = "OFF"; if (togglePower) str = "OFF";
if (GUILayout.Button("Power " + str)) togglePower = !togglePower; if (GUILayout.Button("Power " + str)) togglePower = !togglePower;
if (togglePower) if (togglePower)
{ {
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
{ {
GUIStyle label_txt_red = new GUIStyle(GUI.skin.label); GUIStyle label_txt_red = new GUIStyle(GUI.skin.label);
label_txt_red.normal.textColor = Color.red; label_txt_red.normal.textColor = Color.red;
label_txt_red.alignment = TextAnchor.MiddleCenter; label_txt_red.alignment = TextAnchor.MiddleCenter;
GUILayout.Label("-- POWER LOST --", label_txt_red); GUILayout.Label("-- POWER LOST --", label_txt_red);
} }
   
this.configWindowMinimized = !GUILayout.Toggle (!this.configWindowMinimized, "Configuration"); this.configWindowMinimized = !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()
{ {
this.consumeResource = GUILayout.Toggle (this.consumeResource, "Consume Resources"); this.consumeResource = GUILayout.Toggle (this.consumeResource, "Consume Resources");
   
foreach (IVOID_Module mod in this.Modules) foreach (IVOID_Module mod in this.Modules)
{ {
mod.DrawConfigurables (); mod.DrawConfigurables ();
} }
} }
   
public override void DrawGUI() public override void DrawGUI()
{ {
if (!this._modulesLoaded) if (!this._modulesLoaded)
{ {
this.LoadModules (); this.LoadModules ();
} }
   
  this._windowID = this.windowBaseID;
   
GUI.skin = this.Skin; GUI.skin = this.Skin;
   
int windowID = this.windowBaseID; if (!this.GUIStylesLoaded)
  {
  this.LoadGUIStyles ();
  }
   
this.VOIDIconTexture = this.VOIDIconOff; //icon off default this.VOIDIconTexture = this.VOIDIconOff; //icon off default
if (this.togglePower) this.VOIDIconTexture = this.VOIDIconOn; //or on if power_toggle==true if (this.togglePower) this.VOIDIconTexture = this.VOIDIconOn; //or on if power_toggle==true
if (GUI.Button(new Rect(VOIDIconPos), VOIDIconTexture, new GUIStyle())) if (GUI.Button(new Rect(VOIDIconPos), VOIDIconTexture, new GUIStyle()))
{ {
this.mainGuiMinimized = !this.mainGuiMinimized; this.mainGuiMinimized = !this.mainGuiMinimized;
} }
   
if (!this.mainGuiMinimized) if (!this.mainGuiMinimized)
{ {
Rect _mainWindowPos = this.mainWindowPos; Rect _mainWindowPos = this.mainWindowPos;
   
_mainWindowPos = GUILayout.Window ( _mainWindowPos = GUILayout.Window (
++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)
); );
   
if (_mainWindowPos != this.mainWindowPos) if (_mainWindowPos != this.mainWindowPos)
{ {
this.mainWindowPos = _mainWindowPos; this.mainWindowPos = _mainWindowPos;
} }
} }
   
if (!this.configWindowMinimized) if (!this.configWindowMinimized)
{ {
Rect _configWindowPos = this.configWindowPos; Rect _configWindowPos = this.configWindowPos;
   
_configWindowPos = GUILayout.Window ( _configWindowPos = GUILayout.Window (
++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)
); );
   
if (_configWindowPos != this.configWindowPos) if (_configWindowPos != this.configWindowPos)
{ {
this.configWindowPos = _configWindowPos; this.configWindowPos = _configWindowPos;
} }
} }
} }
   
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 override void SaveConfig() public override void SaveConfig()
{ {
if (!this.configDirty) if (!this.configDirty)
{ {
return; return;
} }
   
base.SaveConfig (); base.SaveConfig ();
   
foreach (IVOID_Module module in this.Modules) foreach (IVOID_Module module in this.Modules)
{ {
module.SaveConfig (); module.SaveConfig ();
} }
   
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 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
* */ * */
protected new bool _hasConfigurables = true; protected new bool _hasConfigurables = true;
   
[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 Vessel vessel = null;  
   
/* /*
* 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.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.normal.textColor = this.textColors [this.ColorIndex]; this.labelStyle.normal.textColor = this.textColors [this.ColorIndex];
   
Tools.PostDebugMessage ("VOID_HUD: Constructed."); Tools.PostDebugMessage ("VOID_HUD: Constructed.");
} }
   
public override void DrawGUI() public override void DrawGUI()
{ {
Tools.PostDebugMessage ("VOID_HUD: Drawing GUI."); Tools.PostDebugMessage ("VOID_HUD: Drawing GUI.");
   
GUI.skin = VOID_Core.Instance.Skin; GUI.skin = VOID_Core.Instance.Skin;
   
if (vessel == null) if (this.vessel == null)
{ {
vessel = FlightGlobals.ActiveVessel; return;
}  
   
if (vessel != FlightGlobals.ActiveVessel)  
{  
vessel = FlightGlobals.ActiveVessel;  
} }
   
if (VOID_Core.Instance.powerAvailable) if (VOID_Core.Instance.powerAvailable)
{ {
labelStyle.normal.textColor = textColors [ColorIndex]; labelStyle.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 (this.vessel.orbit.altitude) + "m" +
" Obt Vel: " + Tools.MuMech_ToSI (vessel.orbit.vel.magnitude) + "m/s" + " Obt Vel: " + Tools.MuMech_ToSI (this.vessel.orbit.vel.magnitude) + "m/s" +
"\nAp: " + Tools.MuMech_ToSI (vessel.orbit.ApA) + "m" + "\nAp: " + Tools.MuMech_ToSI (this.vessel.orbit.ApA) + "m" +
" ETA " + Tools.ConvertInterval (vessel.orbit.timeToAp) + " ETA " + Tools.ConvertInterval (this.vessel.orbit.timeToAp) +
"\nPe: " + Tools.MuMech_ToSI (vessel.orbit.PeA) + "m" + "\nPe: " + Tools.MuMech_ToSI (this.vessel.orbit.PeA) + "m" +
" ETA " + Tools.ConvertInterval (vessel.orbit.timeToPe) + " ETA " + Tools.ConvertInterval (this.vessel.orbit.timeToPe) +
"\nInc: " + vessel.orbit.inclination.ToString ("F3") + "°", "\nInc: " + this.vessel.orbit.inclination.ToString ("F3") + "°",
labelStyle); labelStyle);
// 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 (this.vessel)) + "m" +
" Srf Vel: " + Tools.MuMech_ToSI (vessel.srf_velocity.magnitude) + "m/s" + " Srf Vel: " + Tools.MuMech_ToSI (this.vessel.srf_velocity.magnitude) + "m/s" +
"\nVer: " + Tools.MuMech_ToSI (vessel.verticalSpeed) + "m/s" + "\nVer: " + Tools.MuMech_ToSI (this.vessel.verticalSpeed) + "m/s" +
" Hor: " + Tools.MuMech_ToSI (vessel.horizontalSrfSpeed) + "m/s" + " Hor: " + Tools.MuMech_ToSI (this.vessel.horizontalSrfSpeed) + "m/s" +
"\nLat: " + Tools.GetLatitudeString (vessel, "F3") + "\nLat: " + Tools.GetLatitudeString (this.vessel, "F3") +
" Lon: " + Tools.GetLongitudeString (vessel, "F3") + " Lon: " + Tools.GetLongitudeString (this.vessel, "F3") +
"\nHdg: " + Tools.MuMech_get_heading (vessel).ToString ("F2") + "° " + "\nHdg: " + Tools.MuMech_get_heading (this.vessel).ToString ("F2") + "° " +
Tools.get_heading_text (Tools.MuMech_get_heading (vessel)) + Tools.get_heading_text (Tools.MuMech_get_heading (this.vessel)) +
"\nBiome: " + Tools.Toadicus_GetAtt (vessel).name, "\nBiome: " + Tools.Toadicus_GetAtt (this.vessel).name,
labelStyle); labelStyle);
} }
else else
{ {
labelStyle.normal.textColor = Color.red; labelStyle.normal.textColor = Color.red;
GUI.Label (new Rect ((Screen.width * .2083f), 0, 300f, 70f), "-- POWER LOST --", labelStyle); GUI.Label (new Rect ((Screen.width * .2083f), 0, 300f, 70f), "-- POWER LOST --", labelStyle);
GUI.Label (new Rect ((Screen.width * .625f), 0, 300f, 70f), "-- POWER LOST --", labelStyle); GUI.Label (new Rect ((Screen.width * .625f), 0, 300f, 70f), "-- POWER LOST --", 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_Module.cs // VOID_Module.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 System.Reflection; using System.Reflection;
   
namespace VOID namespace VOID
{ {
public abstract class VOID_Module : IVOID_Module public abstract class VOID_Module : IVOID_Module
{ {
/* /*
* Fields * Fields
* */ * */
[AVOID_SaveValue("Active")] [AVOID_SaveValue("Active")]
protected VOID_SaveValue<bool> _Active = true; protected VOID_SaveValue<bool> _Active = true;
protected bool _Running = false; protected bool _Running = false;
protected bool _hasConfigurables = false;  
   
protected string _Name; protected string _Name;
   
/* /*
* Properties * Properties
* */ * */
public virtual bool hasConfigurables  
{  
get  
{  
return this._hasConfigurables;  
}  
}  
   
public virtual bool toggleActive public virtual bool toggleActive
{ {
get get
{ {
return this._Active; return this._Active;
} }
set set
{ {
this._Active = value; this._Active = value;
} }
} }
   
public virtual bool guiRunning public virtual bool guiRunning
{ {
get get
{ {
return this._Running; return this._Running;
} }
} }
   
public virtual string Name public virtual string Name
{ {
get get
{ {
return this._Name; return this._Name;
  }
  }
   
  public virtual Vessel vessel
  {
  get
  {
  return FlightGlobals.ActiveVessel;
} }
} }
   
/* /*
* Methods * Methods
* */ * */
public void StartGUI() public void StartGUI()
{ {
if (!this.toggleActive) if (!this.toggleActive)
{ {
return; return;
} }
   
Tools.PostDebugMessage (string.Format("Adding {0} to the draw queue.", this.GetType().Name)); Tools.PostDebugMessage (string.Format("Adding {0} to the draw queue.", this.GetType().Name));
RenderingManager.AddToPostDrawQueue (3, this.DrawGUI); RenderingManager.AddToPostDrawQueue (3, this.DrawGUI);
this._Running = true; this._Running = true;
} }
   
public void StopGUI() public void StopGUI()
{ {
Tools.PostDebugMessage (string.Format("Removing {0} from the draw queue.", this.GetType().Name)); Tools.PostDebugMessage (string.Format("Removing {0} from the draw queue.", this.GetType().Name));
RenderingManager.RemoveFromPostDrawQueue (3, this.DrawGUI); RenderingManager.RemoveFromPostDrawQueue (3, this.DrawGUI);
this._Running = false; this._Running = false;
} }
   
public abstract void DrawGUI(); public abstract void DrawGUI();
   
public virtual void DrawConfigurables() {} public virtual void DrawConfigurables() {}
   
public virtual void LoadConfig() public virtual void LoadConfig()
{ {
var config = KSP.IO.PluginConfiguration.CreateForType<VOID_Core> (); var config = KSP.IO.PluginConfiguration.CreateForType<VOID_Core> ();
config.load (); config.load ();
   
foreach (var field in this.GetType().GetFields( foreach (var field in this.GetType().GetFields(
BindingFlags.NonPublic | BindingFlags.NonPublic |
BindingFlags.Public | BindingFlags.Public |
BindingFlags.Instance BindingFlags.Instance
)) ))
{ {
object[] attrs = field.GetCustomAttributes(typeof(AVOID_SaveValue), false); object[] attrs = field.GetCustomAttributes(typeof(AVOID_SaveValue), false);
   
if (attrs.Length == 0) { if (attrs.Length == 0) {
return; return;
} }
   
AVOID_SaveValue attr = attrs.FirstOrDefault () as AVOID_SaveValue; AVOID_SaveValue attr = attrs.FirstOrDefault () as AVOID_SaveValue;
   
string fieldName = string.Format("{0}_{1}", this.GetType().Name, attr.Name); string fieldName = string.Format("{0}_{1}", this.GetType().Name, attr.Name);
   
object fieldValue = field.GetValue(this); object fieldValue = field.GetValue(this);
   
bool convertBack = false; bool convertBack = false;
if (fieldValue is IVOID_SaveValue) if (fieldValue is IVOID_SaveValue)
{ {
fieldValue = (fieldValue as IVOID_SaveValue).AsType; fieldValue = (fieldValue as IVOID_SaveValue).AsType;
convertBack = true; convertBack = true;
} }
   
fieldValue = config.GetValue(fieldName, fieldValue); fieldValue = config.GetValue(fieldName, fieldValue);
   
if (convertBack) if (convertBack)
{ {
Type type = typeof(VOID_SaveValue<>).MakeGenericType (fieldValue.GetType ()); Type type = typeof(VOID_SaveValue<>).MakeGenericType (fieldValue.GetType ());
IVOID_SaveValue convertValue = Activator.CreateInstance (type) as IVOID_SaveValue; IVOID_SaveValue convertValue = Activator.CreateInstance (type) as IVOID_SaveValue;
convertValue.SetValue (fieldValue); convertValue.SetValue (fieldValue);
fieldValue = convertValue; fieldValue = convertValue;
} }
   
field.SetValue (this, fieldValue); field.SetValue (this, fieldValue);
   
Tools.PostDebugMessage(string.Format("{0}: Loaded field {1}.", this.GetType().Name, fieldName)); Tools.PostDebugMessage(string.Format("{0}: Loaded field {1}.", this.GetType().Name, fieldName));
} }
} }
   
public virtual void SaveConfig() public virtual void SaveConfig()
{ {
if (!VOID_Core.Instance.configDirty) if (!VOID_Core.Instance.configDirty)
{ {
return; return;
} }
   
var config = KSP.IO.PluginConfiguration.CreateForType<VOID_Core> (); var config = KSP.IO.PluginConfiguration.CreateForType<VOID_Core> ();
config.load (); config.load ();
   
foreach (var field in this.GetType().GetFields( foreach (var field in this.GetType().GetFields(
BindingFlags.NonPublic | BindingFlags.NonPublic |
BindingFlags.Public | BindingFlags.Public |
BindingFlags.Instance BindingFlags.Instance
)) ))
{ {
object[] attrs = field.GetCustomAttributes(typeof(AVOID_SaveValue), false); object[] attrs = field.GetCustomAttributes(typeof(AVOID_SaveValue), false);
   
if (attrs.Length == 0) { if (attrs.Length == 0) {
return; return;
} }
   
AVOID_SaveValue attr = attrs.FirstOrDefault () as AVOID_SaveValue; AVOID_SaveValue attr = attrs.FirstOrDefault () as AVOID_SaveValue;
   
string fieldName = string.Format("{0}_{1}", this.GetType().Name, attr.Name); string fieldName = string.Format("{0}_{1}", this.GetType().Name, attr.Name);
   
object fieldValue = field.GetValue(this); object fieldValue = field.GetValue(this);
   
if (fieldValue is IVOID_SaveValue) if (fieldValue is IVOID_SaveValue)
{ {
fieldValue = (fieldValue as IVOID_SaveValue).AsType; fieldValue = (fieldValue as IVOID_SaveValue).AsType;
} }
   
config.SetValue(fieldName, fieldValue); config.SetValue(fieldName, fieldValue);
   
Tools.PostDebugMessage(string.Format("{0}: Saved field {1}.", this.GetType().Name, fieldName)); Tools.PostDebugMessage(string.Format("{0}: Saved field {1}.", this.GetType().Name, fieldName));
} }
   
config.save (); config.save ();
} }
} }
} }
   
   
file:b/VOID_Orbital.cs (new)
  //
  // VOID_Orbital.cs
  //
  // Author:
  // toadicus <>
  //
  // Copyright (c) 2013 toadicus
  //
  // This program is free software: you can redistribute it and/or modify
  // it under the terms of the GNU General Public License as published by
  // the Free Software Foundation, either version 3 of the License, or
  // (at your option) any later version.
  //
  // This program is distributed in the hope that it will be useful,
  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  // GNU General Public License for more details.
  //
  // You should have received a copy of the GNU General Public License
  // along with this program. If not, see <http://www.gnu.org/licenses/>.
  using KSP;
  using System;
  using UnityEngine;
 
  namespace VOID
  {
  public class VOID_Orbital : VOID_Module
  {
  protected new string _Name = "Orbital Information";
 
  [AVOID_SaveValue("OrbitalWindowPos")]
  protected Rect OrbitalWindowPos = new Rect(Screen.width / 2, Screen.height / 2, 10f, 10f);
 
  [AVOID_SaveValue("toggleExtendedOribtal")]
  protected bool toggleExtendedOribtal = false;
 
  public void OrbitalWindow(int _)
  {
  // Toadicus edit: added local sidereal longitude.
  double LSL = vessel.longitude + vessel.orbit.referenceBody.rotationAngle;
  LSL = Tools.FixDegreeDomain (LSL);
 
  GUILayout.BeginVertical();
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label(VOIDLabels.void_primary + ":");
  GUILayout.Label(vessel.mainBody.bodyName, GUILayout.ExpandWidth(false));
  GUILayout.EndHorizontal();
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label(VOIDLabels.void_altitude_asl + ":");
  GUILayout.Label(Tools.MuMech_ToSI(vessel.orbit.altitude) + "m", GUILayout.ExpandWidth(false));
  GUILayout.EndHorizontal();
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label(VOIDLabels.void_velocity + ":");
  GUILayout.Label(Tools.MuMech_ToSI(vessel.orbit.vel.magnitude) + "m/s", GUILayout.ExpandWidth(false));
  GUILayout.EndHorizontal();
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label(VOIDLabels.void_apoapsis + ":");
  GUILayout.Label(Tools.MuMech_ToSI(vessel.orbit.ApA) + "m", GUILayout.ExpandWidth(false));
  GUILayout.EndHorizontal();
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label("Time to Ap:");
  GUILayout.Label(Tools.ConvertInterval(vessel.orbit.timeToAp), GUILayout.ExpandWidth(false));
  GUILayout.EndHorizontal();
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label(VOIDLabels.void_periapsis + ":");
  GUILayout.Label(Tools.MuMech_ToSI(vessel.orbit.PeA) + "m", GUILayout.ExpandWidth(false));
  GUILayout.EndHorizontal();
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label("Time to Pe:");
  GUILayout.Label(Tools.ConvertInterval(vessel.orbit.timeToPe), GUILayout.ExpandWidth(false));
  GUILayout.EndHorizontal();
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label("Inclination:");
  GUILayout.Label(vessel.orbit.inclination.ToString("F3") + "°", GUILayout.ExpandWidth(false));
  GUILayout.EndHorizontal();
 
  double r_vessel = vessel.mainBody.Radius + vessel.mainBody.GetAltitude(vessel.findWorldCenterOfMass());
  double g_vessel = (VOID_Core.Constant_G * vessel.mainBody.Mass) / Math.Pow(r_vessel, 2);
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label("Gravity:");
  GUILayout.Label(Tools.MuMech_ToSI(g_vessel) + "m/s²", GUILayout.ExpandWidth(false));
  GUILayout.EndHorizontal();
 
  toggleExtendedOribtal = GUILayout.Toggle(toggleExtendedOribtal, "Extended info");
 
  if (toggleExtendedOribtal)
  {
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label("Period:");
  GUILayout.Label(Tools.ConvertInterval(vessel.orbit.period), GUILayout.ExpandWidth(false));
  GUILayout.EndHorizontal();
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label("Semi-major axis:");
  GUILayout.Label((vessel.orbit.semiMajorAxis / 1000).ToString("##,#") + "km", GUILayout.ExpandWidth(false));
  GUILayout.EndHorizontal();
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label("Eccentricity:");
  GUILayout.Label(vessel.orbit.eccentricity.ToString("F4"), GUILayout.ExpandWidth(false));
  GUILayout.EndHorizontal();
 
  // Toadicus edit: convert mean anomaly into degrees.
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label("Mean anomaly:");
  GUILayout.Label((vessel.orbit.meanAnomaly * 180d / Math.PI).ToString("F3") + "°", GUILayout.ExpandWidth(false));
  GUILayout.EndHorizontal();
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label("True anomaly:");
  GUILayout.Label(vessel.orbit.trueAnomaly.ToString("F3") + "°", GUILayout.ExpandWidth(false));
  GUILayout.EndHorizontal();
 
  // Toadicus edit: convert eccentric anomaly into degrees.
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label("Eccentric anomaly:");
  GUILayout.Label((vessel.orbit.eccentricAnomaly * 180d / Math.PI).ToString("F3") + "°", GUILayout.ExpandWidth(false));
  GUILayout.EndHorizontal();
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label("Long. ascending node:");
  GUILayout.Label(vessel.orbit.LAN.ToString("F3") + "°", GUILayout.ExpandWidth(false));
  GUILayout.EndHorizontal();
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label("Arg. of periapsis:");
  GUILayout.Label(vessel.orbit.argumentOfPeriapsis.ToString("F3") + "°", GUILayout.ExpandWidth(false));
  GUILayout.EndHorizontal();
 
  // Toadicus edit: added local sidereal longitude.
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label("Local Sidereal Longitude:");
  GUILayout.Label(LSL.ToString("F3") + "°", VOID_Core.Instance.LabelStyles["txt_right"]);
  GUILayout.EndHorizontal();
  }
 
  GUILayout.EndVertical();
  GUI.DragWindow();
  }
 
  public override void DrawGUI()
  {
  OrbitalWindowPos = GUILayout.Window(
  ++VOID_Core.Instance.windowID,
  OrbitalWindowPos,
  this.OrbitalWindow,
  this.Name, GUILayout.Width(250),
  GUILayout.Height(50));
  }
  }
  }