Moved IntCollection to ToadicusTools.
Moved IntCollection to ToadicusTools.

file:a/IntCollection.cs (deleted)
//  
// IntCollection.cs  
//  
// Author:  
// toadicus <>  
//  
// Copyright (c) 2013 toadicus  
//  
// This program is free software: you can redistribute it and/or modify  
// it under the terms of the GNU General Public License as published by  
// the Free Software Foundation, either version 3 of the License, or  
// (at your option) any later version.  
//  
// This program is distributed in the hope that it will be useful,  
// but WITHOUT ANY WARRANTY; without even the implied warranty of  
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the  
// GNU General Public License for more details.  
//  
// You should have received a copy of the GNU General Public License  
// along with this program. If not, see <http://www.gnu.org/licenses/>.  
using System;  
 
namespace VOID  
{  
public class IntCollection  
{  
public static implicit operator long(IntCollection c)  
{  
return c.collection;  
}  
 
protected long mask;  
 
public long collection { get; protected set; }  
public ushort maxCount { get; protected set; }  
public ushort wordLength { get; protected set; }  
 
public IntCollection (ushort wordLength = 4, long initialCollection = 0)  
{  
this.collection = initialCollection;  
this.wordLength = wordLength;  
this.maxCount = (ushort)((sizeof(long) * 8 - 1) / wordLength);  
this.mask = ((1 << this.wordLength) - 1);  
}  
 
public ushort this[int idx]  
{  
get {  
if (idx < 0) {  
idx += this.maxCount;  
}  
 
if (idx >= maxCount || idx < 0) {  
throw new IndexOutOfRangeException ();  
}  
 
idx *= wordLength;  
 
return (ushort)((this.collection & (this.mask << idx)) >> idx);  
}  
set {  
if (idx < 0) {  
idx += this.maxCount;  
}  
 
if (idx >= maxCount || idx < 0) {  
throw new IndexOutOfRangeException ();  
}  
 
idx *= wordLength;  
 
long packvalue = value & this.mask;  
 
this.collection &= ~(this.mask << idx);  
this.collection |= packvalue << idx;  
}  
}  
}  
}  
 
 
file:a/Tools.cs (deleted)
//  
// Tools.cs  
//  
// Author:  
// toadicus  
//  
// Copyright (c) 2013 toadicus  
//  
// This program is free software: you can redistribute it and/or modify  
// it under the terms of the GNU General Public License as published by  
// the Free Software Foundation, either version 3 of the License, or  
// (at your option) any later version.  
//  
// This program is distributed in the hope that it will be useful,  
// but WITHOUT ANY WARRANTY; without even the implied warranty of  
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the  
// GNU General Public License for more details.  
//  
// You should have received a copy of the GNU General Public License  
// along with this program. If not, see <http://www.gnu.org/licenses/>.  
//  
// This software uses VesselSimulator and Engineer.Extensions from Engineer Redux.  
// Engineer Redux (c) 2013 cybutek  
// Used by permission.  
//  
///////////////////////////////////////////////////////////////////////////////  
 
using System;  
using System.Collections.Generic;  
using UnityEngine;  
 
namespace VOID  
{  
public static class VOIDLabels  
{  
public static string void_primary = "Primary";  
public static string void_altitude_asl = "Altitude (ASL)";  
public static string void_velocity = "Velocity";  
public static string void_apoapsis = "Apoapsis";  
public static string void_periapsis = "Periapsis";  
}  
 
public static class Tools  
{  
// Toadicus edit: Added re-implementation of the CBAttributeMap.GetAtt function that does not fire a debug message to the game screen.  
public static CBAttributeMap.MapAttribute Toadicus_GetAtt(Vessel vessel)  
{  
CBAttributeMap.MapAttribute mapAttribute;  
 
try  
{  
CBAttributeMap BiomeMap = vessel.mainBody.BiomeMap;  
 
double lat = vessel.latitude * Math.PI / 180d;  
double lon = vessel.longitude * Math.PI / 180d;  
 
mapAttribute = BiomeMap.GetAtt(lat, lon);  
 
/*  
lon -= Math.PI / 2d;  
 
if (lon < 0d)  
{  
lon += 2d * Math.PI;  
}  
 
float v = (float)(lat / Math.PI) + 0.5f;  
float u = (float)(lon / (2d * Math.PI));  
 
Color pixelBilinear = BiomeMap.Map.GetPixelBilinear(u, v);  
mapAttribute = BiomeMap.defaultAttribute;  
 
if (BiomeMap.Map != null)  
{  
if (BiomeMap.exactSearch)  
{  
for (int i = 0; i < BiomeMap.Attributes.Length; ++i)  
{  
if (pixelBilinear == BiomeMap.Attributes[i].mapColor)  
{  
mapAttribute = BiomeMap.Attributes[i];  
}  
}  
}  
else  
{  
float zero = 0;  
float num = 1 / zero;  
for (int j = 0; j < BiomeMap.Attributes.Length; ++j)  
{  
Color mapColor = BiomeMap.Attributes[j].mapColor;  
float sqrMagnitude = ((Vector4)(mapColor - pixelBilinear)).sqrMagnitude;  
if (sqrMagnitude < num)  
{  
bool testCase = true;  
if (BiomeMap.nonExactThreshold != -1)  
{  
testCase = (sqrMagnitude < BiomeMap.nonExactThreshold);  
}  
if (testCase)  
{  
mapAttribute = BiomeMap.Attributes[j];  
num = sqrMagnitude;  
}  
}  
}  
}  
}  
*/  
}  
catch (NullReferenceException)  
{  
mapAttribute = new CBAttributeMap.MapAttribute();  
mapAttribute.name = "N/A";  
}  
 
return mapAttribute;  
}  
 
public static string GetLongitudeString(Vessel vessel, string format = "F4")  
{  
string dir_long = "W";  
double v_long = vessel.longitude;  
 
v_long = FixDegreeDomain(v_long);  
 
if (v_long < -180d)  
{  
v_long += 360d;  
}  
if (v_long >= 180)  
{  
v_long -= 360d;  
}  
 
if (v_long > 0)  
dir_long = "E";  
 
return string.Format("{0}° {1}", Math.Abs(v_long).ToString(format), dir_long);  
}  
 
public static string GetLatitudeString(Vessel vessel, string format = "F4")  
{  
string dir_lat = "S";  
double v_lat = vessel.latitude;  
if (v_lat > 0)  
dir_lat = "N";  
 
return string.Format("{0}° {1}", Math.Abs(v_lat).ToString(format), dir_lat);  
}  
 
///////////////////////////////////////////////////////////////////////////////  
 
//For MuMech_get_heading()  
public class MuMech_MovingAverage  
{  
private double[] store;  
private int storeSize;  
private int nextIndex = 0;  
 
public double value  
{  
get  
{  
double tmp = 0;  
foreach (double i in store)  
{  
tmp += i;  
}  
return tmp / storeSize;  
}  
set  
{  
store[nextIndex] = value;  
nextIndex = (nextIndex + 1) % storeSize;  
}  
}  
 
public MuMech_MovingAverage(int size = 10, double startingValue = 0)  
{  
storeSize = size;  
store = new double[size];  
force(startingValue);  
}  
 
public void force(double newValue)  
{  
for (int i = 0; i < storeSize; i++)  
{  
store[i] = newValue;  
}  
}  
 
public static implicit operator double(MuMech_MovingAverage v)  
{  
return v.value;  
}  
 
public override string ToString()  
{  
return value.ToString();  
}  
 
public string ToString(string format)  
{  
return value.ToString(format);  
}  
}  
//From http://svn.mumech.com/KSP/trunk/MuMechLib/VOID.vesselState.cs  
public static double MuMech_get_heading(Vessel vessel)  
{  
Vector3d CoM;  
 
try  
{  
CoM = vessel.findWorldCenterOfMass();  
}  
catch  
{  
return double.NaN;  
}  
 
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;  
 
Quaternion rotationSurface = Quaternion.LookRotation(north, up);  
Quaternion rotationvesselSurface = Quaternion.Inverse(  
Quaternion.Euler(90, 0, 0) *  
Quaternion.Inverse(vessel.transform.rotation) *  
rotationSurface);  
 
return rotationvesselSurface.eulerAngles.y;  
}  
//From http://svn.mumech.com/KSP/trunk/MuMechLib/MuUtils.cs  
public static string MuMech_ToSI(  
double d, int digits = 3, int MinMagnitude = 0, int MaxMagnitude = int.MaxValue  
)  
{  
float exponent = (float)Math.Log10(Math.Abs(d));  
exponent = Mathf.Clamp(exponent, (float)MinMagnitude, (float)MaxMagnitude);  
 
if (exponent >= 0)  
{  
switch ((int)Math.Floor(exponent))  
{  
case 0:  
case 1:  
case 2:  
return d.ToString("F" + digits);  
case 3:  
case 4:  
case 5:  
return (d / 1e3).ToString("F" + digits) + "k";  
case 6:  
case 7:  
case 8:  
return (d / 1e6).ToString("F" + digits) + "M";  
case 9:  
case 10:  
case 11:  
return (d / 1e9).ToString("F" + digits) + "G";  
case 12:  
case 13:  
case 14:  
return (d / 1e12).ToString("F" + digits) + "T";  
case 15:  
case 16:  
case 17:  
return (d / 1e15).ToString("F" + digits) + "P";  
case 18:  
case 19:  
case 20:  
return (d / 1e18).ToString("F" + digits) + "E";  
case 21:  
case 22:  
case 23:  
return (d / 1e21).ToString("F" + digits) + "Z";  
default:  
return (d / 1e24).ToString("F" + digits) + "Y";  
}  
}  
else if (exponent < 0)  
{  
switch ((int)Math.Floor(exponent))  
{  
case -1:  
case -2:  
case -3:  
return (d * 1e3).ToString("F" + digits) + "m";  
case -4:  
case -5:  
case -6:  
return (d * 1e6).ToString("F" + digits) + "μ";  
case -7:  
case -8:  
case -9:  
return (d * 1e9).ToString("F" + digits) + "n";  
case -10:  
case -11:  
case -12:  
return (d * 1e12).ToString("F" + digits) + "p";  
case -13:  
case -14:  
case -15:  
return (d * 1e15).ToString("F" + digits) + "f";  
case -16:  
case -17:  
case -18:  
return (d * 1e18).ToString("F" + digits) + "a";  
case -19:  
case -20:  
case -21:  
return (d * 1e21).ToString("F" + digits) + "z";  
default:  
return (d * 1e24).ToString("F" + digits) + "y";  
}  
}  
else  
{  
return "0";  
}  
}  
 
public static string ConvertInterval(double seconds)  
{  
string format_1 = "{0:D1}y {1:D1}d {2:D2}h {3:D2}m {4:D2}.{5:D1}s";  
string format_2 = "{0:D1}d {1:D2}h {2:D2}m {3:D2}.{4:D1}s";  
string format_3 = "{0:D2}h {1:D2}m {2:D2}.{3:D1}s";  
 
TimeSpan interval;  
 
try  
{  
interval = TimeSpan.FromSeconds(seconds);  
}  
catch (OverflowException)  
{  
return "NaN";  
}  
 
int years = interval.Days / 365;  
 
string output;  
if (years > 0)  
{  
output = string.Format(format_1,  
years,  
interval.Days - (years * 365), // subtract years * 365 for accurate day count  
interval.Hours,  
interval.Minutes,  
interval.Seconds,  
interval.Milliseconds.ToString().Substring(0, 1));  
}  
else if (interval.Days > 0)  
{  
output = string.Format(format_2,  
interval.Days,  
interval.Hours,  
interval.Minutes,  
interval.Seconds,  
interval.Milliseconds.ToString().Substring(0, 1));  
}  
else  
{  
output = string.Format(format_3,  
interval.Hours,  
interval.Minutes,  
interval.Seconds,  
interval.Milliseconds.ToString().Substring(0, 1));  
}  
return output;  
}  
 
public static string UppercaseFirst(string s)  
{  
if (string.IsNullOrEmpty(s))  
{  
return string.Empty;  
}  
char[] a = s.ToCharArray();  
a[0] = char.ToUpper(a[0]);  
return new string(a);  
}  
//transfer angles  
public static double Nivvy_CalcTransferPhaseAngle(double r_current, double r_target, double grav_param)  
{  
double T_target = (2 * Math.PI) * Math.Sqrt(Math.Pow((r_target / 1000), 3) / (grav_param / 1000000000));  
double T_transfer = (2 * Math.PI) * Math.Sqrt(Math.Pow((((r_target / 1000) + (r_current / 1000)) / 2), 3) / (grav_param / 1000000000));  
return 360 * (0.5 - (T_transfer / (2 * T_target)));  
}  
 
public static double Younata_DeltaVToGetToOtherBody(double mu, double r1, double r2)  
{  
/*  
def deltaVToGetToOtherBody(mu, r1, r2):  
# mu = gravity param of common orbiting body of r1 and r2  
# (e.g. for mun to minmus, mu is kerbin's gravity param  
# r1 = initial body's orbit radius  
# r2 = target body's orbit radius  
 
# return value is km/s  
sur1 = math.sqrt(mu / r1)  
sr1r2 = math.sqrt(float(2*r2)/float(r1+r2))  
mult = sr1r2 - 1  
return sur1 * mult  
*/  
double sur1, sr1r2, mult;  
sur1 = Math.Sqrt(mu / r1);  
sr1r2 = Math.Sqrt((2 * r2) / (r1 + r2));  
mult = sr1r2 - 1;  
return sur1 * mult;  
}  
 
public static double Younata_DeltaVToExitSOI(double mu, double r1, double r2, double v)  
{  
/*  
def deltaVToExitSOI(mu, r1, r2, v):  
# mu = gravity param of current body  
# r1 = current orbit radius  
# r2 = SOI radius  
# v = SOI exit velocity  
foo = r2 * (v**2) - 2 * mu  
bar = r1 * foo + (2 * r2 * mu)  
r = r1*r2  
return math.sqrt(bar / r)  
*/  
double foo = r2 * Math.Pow(v, 2) - 2 * mu;  
double bar = r1 * foo + (2 * r2 * mu);  
double r = r1 * r2;  
return Math.Sqrt(bar / r);  
}  
 
public static double Younata_TransferBurnPoint(double r, double v, double angle, double mu)  
{  
/*  
def transferBurnPoint(r, v, angle, mu):  
# r = parking orbit radius  
# v = ejection velocity  
# angle = phase angle (from function phaseAngle())  
# mu = gravity param of current body.  
epsilon = ((v**2)/2) - (mu / r)  
h = r * v * math.sin(angle)  
e = math.sqrt(1 + ((2 * epsilon * h**2)/(mu**2)))  
theta = math.acos(1.0 / e)  
degrees = theta * (180.0 / math.pi)  
return 180 - degrees  
*/  
double epsilon, h, ee, theta, degrees;  
epsilon = (Math.Pow(v, 2) / 2) - (mu / r);  
h = r * v * Math.Sin(angle);  
ee = Math.Sqrt(1 + ((2 * epsilon * Math.Pow(h, 2)) / Math.Pow(mu, 2)));  
theta = Math.Acos(1.0 / ee);  
degrees = theta * (180.0 / Math.PI);  
return 180 - degrees;  
// returns the ejection angle  
}  
 
public static double Adammada_CurrrentPhaseAngle(  
double body_LAN,  
double body_orbitPct,  
double origin_LAN,  
double origin_orbitPct  
)  
{  
double angle = (body_LAN / 360 + body_orbitPct) - (origin_LAN / 360 + origin_orbitPct);  
if (angle > 1)  
angle = angle - 1;  
if (angle < 0)  
angle = angle + 1;  
if (angle > 0.5)  
angle = angle - 1;  
angle = angle * 360;  
return angle;  
}  
 
public static double Adammada_CurrentEjectionAngle(  
double vessel_long,  
double origin_rotAngle,  
double origin_LAN,  
double origin_orbitPct  
)  
{  
//double eangle = ((FlightGlobals.ActiveVOID.vessel.longitude + orbiting.rotationAngle) - (orbiting.orbit.LAN / 360 + orbiting.orbit.orbitPercent) * 360);  
double eangle = ((vessel_long + origin_rotAngle) - (origin_LAN / 360 + origin_orbitPct) * 360);  
 
while (eangle < 0)  
eangle = eangle + 360;  
while (eangle > 360)  
eangle = eangle - 360;  
if (eangle < 270)  
eangle = 90 - eangle;  
else  
eangle = 450 - eangle;  
return eangle;  
}  
 
public static double mrenigma03_calcphase(Vessel vessel, CelestialBody target) //calculates phase angle between the current body and target body  
{  
Vector3d vecthis = new Vector3d();  
Vector3d vectarget = new Vector3d();  
vectarget = target.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime());  
 
if ((vessel.mainBody.name == "Sun") || (vessel.mainBody.referenceBody.referenceBody.name == "Sun"))  
{  
vecthis = vessel.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime());  
}  
else  
{  
vecthis = vessel.mainBody.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime());  
}  
 
vecthis = Vector3d.Project(new Vector3d(vecthis.x, 0, vecthis.z), vecthis);  
vectarget = Vector3d.Project(new Vector3d(vectarget.x, 0, vectarget.z), vectarget);  
 
Vector3d prograde = new Vector3d();  
prograde = Quaternion.AngleAxis(90, Vector3d.forward) * vecthis;  
 
double phase = Vector3d.Angle(vecthis, vectarget);  
 
if (Vector3d.Angle(prograde, vectarget) > 90)  
phase = 360 - phase;  
 
return (phase + 360) % 360;  
}  
 
public static double FixAngleDomain(double Angle, bool Degrees = false)  
{  
double Extent = 2d * Math.PI;  
if (Degrees)  
{  
Extent = 360d;  
}  
 
Angle = Angle % (Extent);  
if (Angle < 0d)  
{  
Angle += Extent;  
}  
 
return Angle;  
}  
 
public static double FixDegreeDomain(double Angle)  
{  
return FixAngleDomain(Angle, true);  
}  
 
public static double adjustCurrPhaseAngle(double transfer_angle, double curr_phase)  
{  
if (transfer_angle < 0)  
{  
if (curr_phase > 0)  
return (-1 * (360 - curr_phase));  
else if (curr_phase < 0)  
return curr_phase;  
}  
else if (transfer_angle > 0)  
{  
if (curr_phase > 0)  
return curr_phase;  
else if (curr_phase < 0)  
return (360 + curr_phase);  
}  
return curr_phase;  
}  
 
public static double adjust_current_ejection_angle(double curr_ejection)  
{  
//curr_ejection WILL need to be adjusted once for all transfers as it returns values ranging -180 to 180  
// need 0-360 instead  
//  
// ie i have -17 in the screenshot  
// need it to show 343  
//  
// do this  
//  
// if < 0, add curr to 360 // 360 + (-17) = 343  
// else its good as it is  
 
if (curr_ejection < 0)  
return 360 + curr_ejection;  
else  
return curr_ejection;  
 
}  
 
public static double adjust_transfer_ejection_angle(double trans_ejection, double trans_phase)  
{  
// if transfer_phase_angle < 0 its a lower transfer  
//180 + curr_ejection  
// else if transfer_phase_angle > 0 its good as it is  
 
if (trans_phase < 0)  
return 180 + trans_ejection;  
else  
return trans_ejection;  
 
}  
 
public static double TrueAltitude(Vessel vessel)  
{  
double trueAltitude = vessel.orbit.altitude - vessel.terrainAltitude;  
 
// HACK: This assumes that on worlds with oceans, all water is fixed at 0 m,  
// and water covers the whole surface at 0 m.  
if (vessel.terrainAltitude < 0 && vessel.mainBody.ocean)  
{  
trueAltitude = vessel.orbit.altitude;  
}  
 
return trueAltitude;  
}  
 
public static string get_heading_text(double heading)  
{  
if (heading > 348.75 || heading <= 11.25)  
return "N";  
else if (heading > 11.25 && heading <= 33.75)  
return "NNE";  
else if (heading > 33.75 && heading <= 56.25)  
return "NE";  
else if (heading > 56.25 && heading <= 78.75)  
return "ENE";  
else if (heading > 78.75 && heading <= 101.25)  
return "E";  
else if (heading > 101.25 && heading <= 123.75)  
return "ESE";  
else if (heading > 123.75 && heading <= 146.25)  
return "SE";  
else if (heading > 146.25 && heading <= 168.75)  
return "SSE";  
else if (heading > 168.75 && heading <= 191.25)  
return "S";  
else if (heading > 191.25 && heading <= 213.75)  
return "SSW";  
else if (heading > 213.75 && heading <= 236.25)  
return "SW";  
else if (heading > 236.25 && heading <= 258.75)  
return "WSW";  
else if (heading > 258.75 && heading <= 281.25)  
return "W";  
else if (heading > 281.25 && heading <= 303.75)  
return "WNW";  
else if (heading > 303.75 && heading <= 326.25)  
return "NW";  
else if (heading > 326.25 && heading <= 348.75)  
return "NNW";  
else  
return "";  
}  
 
public static void display_transfer_angles_SUN2PLANET(CelestialBody body, Vessel vessel)  
{  
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
GUILayout.Label("Phase angle (curr/trans):");  
GUILayout.Label(  
Tools.mrenigma03_calcphase(vessel, body).ToString("F3") + "° / " + Tools.Nivvy_CalcTransferPhaseAngle(  
vessel.orbit.semiMajorAxis,  
body.orbit.semiMajorAxis,  
vessel.mainBody.gravParameter  
).ToString("F3") + "°",  
GUILayout.ExpandWidth(false)  
);  
GUILayout.EndHorizontal();  
 
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
GUILayout.Label("Transfer velocity:");  
GUILayout.Label(  
(Tools.Younata_DeltaVToGetToOtherBody(  
(vessel.mainBody.gravParameter / 1000000000),  
(vessel.orbit.semiMajorAxis / 1000),  
(body.orbit.semiMajorAxis / 1000)  
) * 1000).ToString("F2") + "m/s",  
GUILayout.ExpandWidth(false)  
);  
GUILayout.EndHorizontal();  
}  
 
public static void display_transfer_angles_PLANET2PLANET(CelestialBody body, Vessel vessel)  
{  
double dv1 = Tools.Younata_DeltaVToGetToOtherBody(  
(vessel.mainBody.referenceBody.gravParameter / 1000000000),  
(vessel.mainBody.orbit.semiMajorAxis / 1000),  
(body.orbit.semiMajorAxis / 1000)  
);  
double dv2 = Tools.Younata_DeltaVToExitSOI(  
(vessel.mainBody.gravParameter / 1000000000),  
(vessel.orbit.semiMajorAxis / 1000),  
(vessel.mainBody.sphereOfInfluence / 1000),  
Math.Abs(dv1)  
);  
 
double trans_ejection_angle = Tools.Younata_TransferBurnPoint(  
(vessel.orbit.semiMajorAxis / 1000),  
dv2,  
(Math.PI / 2.0),  
(vessel.mainBody.gravParameter / 1000000000)  
);  
double curr_ejection_angle = Tools.Adammada_CurrentEjectionAngle(  
FlightGlobals.ActiveVessel.longitude,  
FlightGlobals.ActiveVessel.orbit.referenceBody.rotationAngle,  
FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.LAN,  
FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.orbitPercent  
);  
 
double trans_phase_angle = Tools.Nivvy_CalcTransferPhaseAngle(  
vessel.mainBody.orbit.semiMajorAxis,  
body.orbit.semiMajorAxis,  
vessel.mainBody.referenceBody.gravParameter  
) % 360;  
double curr_phase_angle = Tools.Adammada_CurrrentPhaseAngle(  
body.orbit.LAN,  
body.orbit.orbitPercent,  
FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.LAN,  
FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.orbitPercent  
);  
 
double adj_phase_angle = Tools.adjustCurrPhaseAngle(trans_phase_angle, curr_phase_angle);  
double adj_trans_ejection_angle = Tools.adjust_transfer_ejection_angle(trans_ejection_angle, trans_phase_angle);  
double adj_curr_ejection_angle = Tools.adjust_current_ejection_angle(curr_ejection_angle);  
 
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
GUILayout.Label("Phase angle (curr/trans):");  
GUILayout.Label(  
adj_phase_angle.ToString("F3") + "° / " + trans_phase_angle.ToString("F3") + "°",  
GUILayout.ExpandWidth(false)  
);  
GUILayout.EndHorizontal();  
 
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
GUILayout.Label("Ejection angle (curr/trans):");  
GUILayout.Label(  
adj_curr_ejection_angle.ToString("F3") + "° / " + adj_trans_ejection_angle.ToString("F3") + "°",  
GUILayout.ExpandWidth(false)  
);  
GUILayout.EndHorizontal();  
 
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
GUILayout.Label("Transfer velocity:");  
GUILayout.Label((dv2 * 1000).ToString("F2") + "m/s", GUILayout.ExpandWidth(false));  
GUILayout.EndHorizontal();  
}  
 
public static void display_transfer_angles_PLANET2MOON(CelestialBody body, Vessel vessel)  
{  
double dv1 = Tools.Younata_DeltaVToGetToOtherBody(  
(vessel.mainBody.gravParameter / 1000000000),  
(vessel.orbit.semiMajorAxis / 1000),  
(body.orbit.semiMajorAxis / 1000)  
);  
 
double trans_phase_angle = Tools.Nivvy_CalcTransferPhaseAngle(  
vessel.orbit.semiMajorAxis,  
body.orbit.semiMajorAxis,  
vessel.mainBody.gravParameter  
);  
 
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
GUILayout.Label("Phase angle (curr/trans):");  
GUILayout.Label(  
Tools.mrenigma03_calcphase(vessel, body).ToString("F3") + "° / " + trans_phase_angle.ToString("F3") + "°",  
GUILayout.ExpandWidth(false)  
);  
GUILayout.EndHorizontal();  
 
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
GUILayout.Label("Transfer velocity:");  
GUILayout.Label((dv1 * 1000).ToString("F2") + "m/s", GUILayout.ExpandWidth(false));  
GUILayout.EndHorizontal();  
}  
 
public static void display_transfer_angles_MOON2MOON(CelestialBody body, Vessel vessel)  
{  
double dv1 = Tools.Younata_DeltaVToGetToOtherBody(  
(vessel.mainBody.referenceBody.gravParameter / 1000000000),  
(vessel.mainBody.orbit.semiMajorAxis / 1000),  
(body.orbit.semiMajorAxis / 1000)  
);  
double dv2 = Tools.Younata_DeltaVToExitSOI(  
(vessel.mainBody.gravParameter / 1000000000),  
(vessel.orbit.semiMajorAxis / 1000),  
(vessel.mainBody.sphereOfInfluence / 1000),  
Math.Abs(dv1)  
);  
double trans_ejection_angle = Tools.Younata_TransferBurnPoint(  
(vessel.orbit.semiMajorAxis / 1000),  
dv2,  
(Math.PI / 2.0),  
(vessel.mainBody.gravParameter / 1000000000)  
);  
 
double curr_phase_angle = Tools.Adammada_CurrrentPhaseAngle(  
body.orbit.LAN,  
body.orbit.orbitPercent,  
FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.LAN,  
FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.orbitPercent  
);  
double curr_ejection_angle = Tools.Adammada_CurrentEjectionAngle(  
FlightGlobals.ActiveVessel.longitude,  
FlightGlobals.ActiveVessel.orbit.referenceBody.rotationAngle,  
FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.LAN,  
FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.orbitPercent  
);  
 
double trans_phase_angle = Tools.Nivvy_CalcTransferPhaseAngle(  
vessel.mainBody.orbit.semiMajorAxis,  
body.orbit.semiMajorAxis,  
vessel.mainBody.referenceBody.gravParameter  
) % 360;  
 
double adj_phase_angle = Tools.adjustCurrPhaseAngle(trans_phase_angle, curr_phase_angle);  
//double adj_ejection_angle = adjustCurrEjectionAngle(trans_phase_angle, curr_ejection_angle);  
 
//new stuff  
//  
double adj_trans_ejection_angle = Tools.adjust_transfer_ejection_angle(trans_ejection_angle, trans_phase_angle);  
double adj_curr_ejection_angle = Tools.adjust_current_ejection_angle(curr_ejection_angle);  
//  
//  
 
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
GUILayout.Label("Phase angle (curr/trans):");  
GUILayout.Label(  
adj_phase_angle.ToString("F3") + "° / " + trans_phase_angle.ToString("F3") + "°",  
GUILayout.ExpandWidth(false)  
);  
GUILayout.EndHorizontal();  
 
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
GUILayout.Label("Ejection angle (curr/trans):");  
GUILayout.Label(  
adj_curr_ejection_angle.ToString("F3") + "° / " + adj_trans_ejection_angle.ToString("F3") + "°",  
GUILayout.ExpandWidth(false)  
);  
GUILayout.EndHorizontal();  
 
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
GUILayout.Label("Transfer velocity:");  
GUILayout.Label((dv2 * 1000).ToString("F2") + "m/s", GUILayout.ExpandWidth(false));  
GUILayout.EndHorizontal();  
}  
// This implementation is adapted from FARGUIUtils.ClampToScreen  
public static Rect ClampRectToScreen(Rect window, int xMargin, int yMargin)  
{  
window.x = Mathf.Clamp(window.x, xMargin - window.width, Screen.width - xMargin);  
window.y = Mathf.Clamp(window.y, yMargin - window.height, Screen.height - yMargin);  
 
return window;  
}  
 
public static Rect ClampRectToScreen(Rect window, int Margin)  
{  
return ClampRectToScreen(window, Margin, Margin);  
}  
 
public static Rect ClampRectToScreen(Rect window)  
{  
return ClampRectToScreen(window, 30);  
}  
 
public static Vector2 ClampV2ToScreen(Vector2 vec, uint xMargin, uint yMargin)  
{  
vec.x = Mathf.Clamp(vec.x, xMargin, Screen.width - xMargin);  
vec.y = Mathf.Clamp(vec.y, yMargin, Screen.height - yMargin);  
 
return vec;  
}  
 
public static Vector2 ClampV2ToScreen(Vector2 vec, uint Margin)  
{  
return ClampV2ToScreen(vec, Margin, Margin);  
}  
 
public static Vector2 ClampV2ToScreen(Vector2 vec)  
{  
return ClampV2ToScreen(vec, 15);  
}  
// UNDONE: This seems messy. Can we clean it up?  
public static Rect DockToWindow(Rect icon, Rect window)  
{  
// We can't set the x and y of the center point directly, so build a new vector.  
Vector2 center = new Vector2();  
 
// If we are near the top or bottom of the screen...  
if (window.yMax > Screen.height - icon.height ||  
window.yMin < icon.height)  
{  
// If we are in a corner...  
if (window.xMax > Screen.width - icon.width ||  
window.xMin < icon.width)  
{  
// If it is a top corner, put the icon below the window.  
if (window.yMax < Screen.height / 2)  
{  
center.y = window.yMax + icon.height / 2;  
}  
// If it is a bottom corner, put the icon above the window.  
else  
{  
center.y = window.yMin - icon.height / 2;  
}  
}  
// If we are not in a corner...  
else  
{  
// If we are along the top edge, align the icon's top edge with the top edge of the window  
if (window.yMax > Screen.height / 2)  
{  
center.y = window.yMax - icon.height / 2;  
}  
// If we are along the bottom edge, align the icon's bottom edge with the bottom edge of the window  
else  
{  
center.y = window.yMin + icon.height / 2;  
}  
}  
 
// At the top or bottom, if we are towards the right, put the icon to the right of the window  
if (window.center.x < Screen.width / 2)  
{  
center.x = window.xMin - icon.width / 2;  
}  
// At the top or bottom, if we are towards the left, put the icon to the left of the window  
else  
{  
center.x = window.xMax + icon.width / 2;  
}  
 
}  
// If we are not along the top or bottom of the screen...  
else  
{  
// By default, center the icon above the window  
center.y = window.yMin - icon.height / 2;  
center.x = window.center.x;  
 
// If we are along a side...  
if (window.xMax > Screen.width - icon.width ||  
window.xMin < icon.width)  
{  
// UNDONE: I'm not sure I like the feel of this part.  
// If we are along a side towards the bottom, put the icon below the window  
if (window.center.y > Screen.height / 2)  
{  
center.y = window.yMax + icon.height / 2;  
}  
 
// Along the left side, align the left edge of the icon with the left edge of the window.  
if (window.xMax > Screen.width - icon.width)  
{  
center.x = window.xMax - icon.width / 2;  
}  
// Along the right side, align the right edge of the icon with the right edge of the window.  
else if (window.xMin < icon.width)  
{  
center.x = window.xMin + icon.width / 2;  
}  
}  
}  
 
// Assign the vector to the center of the rect.  
icon.center = center;  
 
// Return the icon's position.  
return icon;  
}  
 
public static ExperimentSituations GetExperimentSituation(this Vessel vessel)  
{  
Vessel.Situations situation = vessel.situation;  
 
switch (situation)  
{  
case Vessel.Situations.PRELAUNCH:  
case Vessel.Situations.LANDED:  
return ExperimentSituations.SrfLanded;  
case Vessel.Situations.SPLASHED:  
return ExperimentSituations.SrfSplashed;  
case Vessel.Situations.FLYING:  
if (vessel.altitude < (double)vessel.mainBody.scienceValues.flyingAltitudeThreshold)  
{  
return ExperimentSituations.FlyingLow;  
}  
else  
{  
return ExperimentSituations.FlyingHigh;  
}  
}  
 
if (vessel.altitude < (double)vessel.mainBody.scienceValues.spaceAltitudeThreshold)  
{  
return ExperimentSituations.InSpaceLow;  
}  
else  
{  
return ExperimentSituations.InSpaceHigh;  
}  
}  
 
public static double Radius(this Vessel vessel)  
{  
double radius;  
 
radius = vessel.altitude;  
 
if (vessel.mainBody != null)  
{  
radius += vessel.mainBody.Radius;  
}  
 
return radius;  
}  
 
public static double TryGetLastMass(this Engineer.VesselSimulator.SimManager simManager)  
{  
if (simManager.Stages == null || simManager.Stages.Length <= Staging.lastStage)  
{  
return double.NaN;  
}  
 
return simManager.Stages[Staging.lastStage].totalMass;  
}  
 
public static string HumanString(this ExperimentSituations situation)  
{  
switch (situation)  
{  
case ExperimentSituations.FlyingHigh:  
return "Upper Atmosphere";  
case ExperimentSituations.FlyingLow:  
return "Flying";  
case ExperimentSituations.SrfLanded:  
return "Surface";  
case ExperimentSituations.InSpaceLow:  
return "Near in Space";  
case ExperimentSituations.InSpaceHigh:  
return "High in Space";  
case ExperimentSituations.SrfSplashed:  
return "Splashed Down";  
default:  
return "Unknown";  
}  
}  
 
private static ScreenMessage debugmsg = new ScreenMessage("", 2f, ScreenMessageStyle.UPPER_RIGHT);  
 
[System.Diagnostics.Conditional("DEBUG")]  
public static void PostDebugMessage(string Msg)  
{  
if (HighLogic.LoadedScene > GameScenes.SPACECENTER)  
{  
debugmsg.message = Msg;  
ScreenMessages.PostScreenMessage(debugmsg, true);  
}  
 
KSPLog.print(Msg);  
}  
}  
}  
  ///////////////////////////////////////////////////////////////////////////////
  //
  // VOID - Vessel Orbital Information Display for Kerbal Space Program
  // Copyright (C) 2012 Iannic-ann-od
  // Copyright (C) 2013 Toadicus
  //
  // This program is free software: you can redistribute it and/or modify
  // it under the terms of the GNU General Public License as published by
  // the Free Software Foundation, either version 3 of the License, or
  // (at your option) any later version.
  //
  // This program is distributed in the hope that it will be useful,
  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  // GNU General Public License for more details.
  //
  // You should have received a copy of the GNU General Public License
  // along with this program. If not, see <http://www.gnu.org/licenses/>.
  //
  ///////////////////////////////////////////////////////////////////////////////
  //
  // Much, much credit to Younata, Adammada, Nivvydaskrl and to all the authors
  // behind MechJeb, RemoteTech Relay Network, ISA MapSat, and Protractor for some
  // invaluable functions and making your nicely written code available to learn from.
  //
  ///////////////////////////////////////////////////////////////////////////////
  //
  // This software uses VesselSimulator and Engineer.Extensions from Engineer Redux.
  // Engineer Redux (c) 2013 cybutek
  // Used by permission.
  //
  ///////////////////////////////////////////////////////////////////////////////
 
  using Engineer.VesselSimulator;
  using KSP;
  using System;
  using ToadicusTools;
  using UnityEngine;
 
  namespace VOID
  {
  [KSPAddon(KSPAddon.Startup.EditorAny, false)]
  public class VOIDEditorMaster : MonoBehaviour
  {
  protected VOID_EditorCore Core;
 
  public void Awake()
  {
  Tools.PostDebugMessage ("VOIDEditorMaster: Waking up.");
  this.Core = VOID_EditorCore.Instance;
  this.Core.ResetGUI ();
  Tools.PostDebugMessage ("VOIDEditorMaster: Awake.");
  }
 
  public void Update()
  {
  if (!HighLogic.LoadedSceneIsEditor && this.Core != null)
  {
  this.Core.SaveConfig ();
  this.Core = null;
  VOID_EditorCore.Reset();
  return;
  }
 
  if (this.Core == null)
  {
  this.Awake();
  }
 
  this.Core.Update ();
 
  if (this.Core.factoryReset)
  {
  KSP.IO.File.Delete<VOID_EditorCore>("config.xml");
  this.Core = null;
  VOID_EditorCore.Reset();
  }
  }
 
  public void FixedUpdate()
  {
  if (this.Core == null || !HighLogic.LoadedSceneIsEditor)
  {
  return;
  }
 
  this.Core.FixedUpdate ();
  }
 
  public void OnGUI()
  {
  if (this.Core == null)
  {
  return;
  }
 
  this.Core.OnGUI();
  }
  }
  }
 
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
// 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 UnityEngine; using UnityEngine;
using Engineer.VesselSimulator; using Engineer.VesselSimulator;
  using ToadicusTools;
   
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();  
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)]  
public class VOIDEditorMaster : MonoBehaviour  
{  
protected VOID_EditorCore Core;  
   
public void Awake()  
{  
Tools.PostDebugMessage ("VOIDEditorMaster: Waking up.");  
this.Core = VOID_EditorCore.Instance;  
this.Core.ResetGUI ();  
SimManager.HardReset();  
Tools.PostDebugMessage ("VOIDEditorMaster: Awake.");  
}  
   
public void Update()  
{  
if (!HighLogic.LoadedSceneIsEditor && this.Core != null)  
{  
this.Core.SaveConfig ();  
this.Core = null;  
VOID_EditorCore.Reset();  
return;  
}  
   
if (this.Core == null)  
{  
this.Awake();  
}  
   
this.Core.Update ();  
   
if (this.Core.factoryReset)  
{  
KSP.IO.File.Delete<VOID_EditorCore>("config.xml");  
this.Core = null;  
VOID_EditorCore.Reset();  
}  
}  
   
public void FixedUpdate()  
{  
if (this.Core == null || !HighLogic.LoadedSceneIsEditor)  
{  
return;  
}  
   
this.Core.FixedUpdate ();  
}  
   
public void OnGUI()  
{  
if (this.Core == null)  
{  
return;  
}  
   
this.Core.OnGUI();  
}  
}  
} }
   
// //
// 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 ToadicusTools;
using UnityEngine; using UnityEngine;
   
namespace VOID namespace VOID
{ {
public class VOID_CBInfoBrowser : VOID_WindowModule public class VOID_CBInfoBrowser : VOID_WindowModule
{ {
[AVOID_SaveValue("selectedBodyIdx1")] [AVOID_SaveValue("selectedBodyIdx1")]
protected VOID_SaveValue<int> selectedBodyIdx1 = 1; protected VOID_SaveValue<int> selectedBodyIdx1 = 1;
   
[AVOID_SaveValue("selectedBodyIdx2")] [AVOID_SaveValue("selectedBodyIdx2")]
protected VOID_SaveValue<int> selectedBodyIdx2 = 2; protected VOID_SaveValue<int> selectedBodyIdx2 = 2;
   
protected CelestialBody selectedBody1; protected CelestialBody selectedBody1;
protected CelestialBody selectedBody2; protected CelestialBody selectedBody2;
   
[AVOID_SaveValue("toggleOrbital")] [AVOID_SaveValue("toggleOrbital")]
protected VOID_SaveValue<bool> toggleOrbital = false; protected VOID_SaveValue<bool> toggleOrbital = false;
   
[AVOID_SaveValue("togglePhysical")] [AVOID_SaveValue("togglePhysical")]
protected VOID_SaveValue<bool> togglePhysical = false; protected VOID_SaveValue<bool> togglePhysical = false;
   
public VOID_CBInfoBrowser() public VOID_CBInfoBrowser()
{ {
this._Name = "Celestial Body Information Browser"; this._Name = "Celestial Body Information Browser";
   
this.WindowPos.x = 10; this.WindowPos.x = 10;
this.WindowPos.y = 85; this.WindowPos.y = 85;
} }
   
public override void ModuleWindow(int _) public override void ModuleWindow(int _)
{ {
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
   
GUILayout.BeginVertical(GUILayout.Width(150)); GUILayout.BeginVertical(GUILayout.Width(150));
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("", GUILayout.ExpandWidth(true)); GUILayout.Label("", GUILayout.ExpandWidth(true));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.EndVertical(); GUILayout.EndVertical();
   
GUILayout.BeginVertical(GUILayout.Width(150)); GUILayout.BeginVertical(GUILayout.Width(150));
   
selectedBody1 = VOID_Core.Instance.allBodies[selectedBodyIdx1]; selectedBody1 = VOID_Core.Instance.allBodies[selectedBodyIdx1];
selectedBody2 = VOID_Core.Instance.allBodies[selectedBodyIdx2]; selectedBody2 = VOID_Core.Instance.allBodies[selectedBodyIdx2];
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
if (GUILayout.Button("<", GUILayout.ExpandWidth(false))) if (GUILayout.Button("<", GUILayout.ExpandWidth(false)))
{ {
selectedBodyIdx1--; selectedBodyIdx1--;
if (selectedBodyIdx1 < 0) selectedBodyIdx1 = VOID_Core.Instance.allBodies.Count - 1; if (selectedBodyIdx1 < 0) selectedBodyIdx1 = VOID_Core.Instance.allBodies.Count - 1;
} }
GUILayout.Label(VOID_Core.Instance.allBodies[selectedBodyIdx1].bodyName, VOID_Core.Instance.LabelStyles["center_bold"], GUILayout.ExpandWidth(true)); GUILayout.Label(VOID_Core.Instance.allBodies[selectedBodyIdx1].bodyName, VOID_Core.Instance.LabelStyles["center_bold"], GUILayout.ExpandWidth(true));
if (GUILayout.Button(">", GUILayout.ExpandWidth(false))) if (GUILayout.Button(">", GUILayout.ExpandWidth(false)))
{ {
selectedBodyIdx1++; selectedBodyIdx1++;
if (selectedBodyIdx1 > VOID_Core.Instance.allBodies.Count - 1) selectedBodyIdx1 = 0; if (selectedBodyIdx1 > VOID_Core.Instance.allBodies.Count - 1) selectedBodyIdx1 = 0;
} }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUILayout.EndVertical(); GUILayout.EndVertical();
   
GUILayout.BeginVertical(GUILayout.Width(150)); GUILayout.BeginVertical(GUILayout.Width(150));
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
if (GUILayout.Button("<", GUILayout.ExpandWidth(false))) if (GUILayout.Button("<", GUILayout.ExpandWidth(false)))
{ {
selectedBodyIdx2--; selectedBodyIdx2--;
if (selectedBodyIdx2 < 0) selectedBodyIdx2 = VOID_Core.Instance.allBodies.Count - 1; if (selectedBodyIdx2 < 0) selectedBodyIdx2 = VOID_Core.Instance.allBodies.Count - 1;
} }
GUILayout.Label(VOID_Core.Instance.allBodies[selectedBodyIdx2].bodyName, VOID_Core.Instance.LabelStyles["center_bold"], GUILayout.ExpandWidth(true)); GUILayout.Label(VOID_Core.Instance.allBodies[selectedBodyIdx2].bodyName, VOID_Core.Instance.LabelStyles["center_bold"], GUILayout.ExpandWidth(true));
if (GUILayout.Button(">", GUILayout.ExpandWidth(false))) if (GUILayout.Button(">", GUILayout.ExpandWidth(false)))
{ {
selectedBodyIdx2++; selectedBodyIdx2++;
if (selectedBodyIdx2 > VOID_Core.Instance.allBodies.Count - 1) selectedBodyIdx2 = 0; if (selectedBodyIdx2 > VOID_Core.Instance.allBodies.Count - 1) selectedBodyIdx2 = 0;
} }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUILayout.EndVertical(); GUILayout.EndVertical();
   
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
//}  
   
//toggle for orbital info chunk //toggle for orbital info chunk
if (GUILayout.Button("Orbital Characteristics", GUILayout.ExpandWidth(true))) toggleOrbital.value = !toggleOrbital; if (GUILayout.Button("Orbital Characteristics", GUILayout.ExpandWidth(true))) toggleOrbital.value = !toggleOrbital;
   
if (toggleOrbital) if (toggleOrbital)
{ {
//begin orbital into horizontal chunk //begin orbital into horizontal chunk
//print("begin orbital info section..."); //print("begin orbital info section...");
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
   
//begin orbital value labels column //begin orbital value labels column
GUILayout.BeginVertical(GUILayout.Width(150)); GUILayout.BeginVertical(GUILayout.Width(150));
   
//print("printing row labels..."); //print("printing row labels...");
   
GUILayout.Label("Apoapsis:"); GUILayout.Label("Apoapsis:");
GUILayout.Label("Time to Ap:"); GUILayout.Label("Time to Ap:");
GUILayout.Label("Periapsis:"); GUILayout.Label("Periapsis:");
GUILayout.Label("Time to Pe:"); GUILayout.Label("Time to Pe:");
GUILayout.Label("Semi-major axis:"); GUILayout.Label("Semi-major axis:");
GUILayout.Label("Eccentricity:"); GUILayout.Label("Eccentricity:");
GUILayout.Label("Orbital period:"); GUILayout.Label("Orbital period:");
GUILayout.Label("Rotational period:"); GUILayout.Label("Rotational period:");
GUILayout.Label("Velocity:"); GUILayout.Label("Velocity:");
GUILayout.Label("Mean anomaly:"); GUILayout.Label("Mean anomaly:");
GUILayout.Label("True anomaly:"); GUILayout.Label("True anomaly:");
GUILayout.Label("Eccentric anomaly:"); GUILayout.Label("Eccentric anomaly:");
GUILayout.Label("Inclination:"); GUILayout.Label("Inclination:");
GUILayout.Label("Long. ascending node:"); GUILayout.Label("Long. ascending node:");
GUILayout.Label("Arg. of periapsis:"); GUILayout.Label("Arg. of periapsis:");
GUILayout.Label("Tidally locked:"); GUILayout.Label("Tidally locked:");
   
//end orbital value labels column //end orbital value labels column
GUILayout.EndVertical(); GUILayout.EndVertical();
   
//begin primary orbital values column //begin primary orbital values column
GUILayout.BeginVertical(GUILayout.Width(150)); GUILayout.BeginVertical(GUILayout.Width(150));
   
body_OP_show_orbital_info(selectedBody1); body_OP_show_orbital_info(selectedBody1);
   
//end primary orbital values column //end primary orbital values column
GUILayout.EndVertical(); GUILayout.EndVertical();
   
//begin secondary orbital values column //begin secondary orbital values column
GUILayout.BeginVertical(GUILayout.Width(150)); GUILayout.BeginVertical(GUILayout.Width(150));
   
body_OP_show_orbital_info(selectedBody2); body_OP_show_orbital_info(selectedBody2);
   
//end secondary orbital values column //end secondary orbital values column
GUILayout.EndVertical(); GUILayout.EndVertical();
   
//end orbital info horizontal chunk //end orbital info horizontal chunk
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
   
//toggle for physical info chunk //toggle for physical info chunk
if (GUILayout.Button("Physical Characteristics", GUILayout.ExpandWidth(true))) togglePhysical.value = !togglePhysical; if (GUILayout.Button("Physical Characteristics", GUILayout.ExpandWidth(true))) togglePhysical.value = !togglePhysical;
   
if (togglePhysical) if (togglePhysical)
{ {
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
   
//begin physical info value label column //begin physical info value label column
GUILayout.BeginVertical(GUILayout.Width(150)); GUILayout.BeginVertical(GUILayout.Width(150));
   
GUILayout.Label("Radius:"); GUILayout.Label("Radius:");
GUILayout.Label("Surface area:"); GUILayout.Label("Surface area:");
GUILayout.Label("Volume:"); GUILayout.Label("Volume:");
GUILayout.Label("Mass:"); GUILayout.Label("Mass:");
GUILayout.Label("Density:"); GUILayout.Label("Density:");
GUILayout.Label("Sphere of influence:"); GUILayout.Label("Sphere of influence:");
GUILayout.Label("Natural satellites:"); GUILayout.Label("Natural satellites:");
GUILayout.Label("Artificial satellites:"); GUILayout.Label("Artificial satellites:");
GUILayout.Label("Surface gravity:"); GUILayout.Label("Surface gravity:");
GUILayout.Label("Atmosphere altitude:"); GUILayout.Label("Atmosphere altitude:");
GUILayout.Label("Atmospheric O\u2082:"); GUILayout.Label("Atmospheric O\u2082:");
GUILayout.Label("Has ocean:"); GUILayout.Label("Has ocean:");
   
//end physical info value label column //end physical info value label column
GUILayout.EndVertical(); GUILayout.EndVertical();
   
//begin primary physical values column //begin primary physical values column
GUILayout.BeginVertical(GUILayout.Width(150)); GUILayout.BeginVertical(GUILayout.Width(150));
   
body_OP_show_physical_info(selectedBody1); body_OP_show_physical_info(selectedBody1);
   
//end primary physical column //end primary physical column
GUILayout.EndVertical(); GUILayout.EndVertical();
   
//begin secondary physical values column //begin secondary physical values column
GUILayout.BeginVertical(GUILayout.Width(150)); GUILayout.BeginVertical(GUILayout.Width(150));
   
body_OP_show_physical_info(selectedBody2); body_OP_show_physical_info(selectedBody2);
   
//end target physical values column //end target physical values column
GUILayout.EndVertical(); GUILayout.EndVertical();
   
//end physical value horizontal chunk //end physical value horizontal chunk
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
   
GUI.DragWindow(); GUI.DragWindow();
} }
   
private void body_OP_show_orbital_info(CelestialBody body) private void body_OP_show_orbital_info(CelestialBody body)
{ {
//GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
else GUILayout.Label((body.orbit.ApA / 1000).ToString("##,#") + "km", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); else GUILayout.Label((body.orbit.ApA / 1000).ToString("##,#") + "km", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
//GUILayout.EndHorizontal();  
   
//GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
else GUILayout.Label(Tools.ConvertInterval(body.orbit.timeToAp), VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); else GUILayout.Label(Tools.ConvertInterval(body.orbit.timeToAp), VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
//GUILayout.EndHorizontal();  
   
//GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
else GUILayout.Label((body.orbit.PeA / 1000).ToString("##,#") + "km", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); else GUILayout.Label((body.orbit.PeA / 1000).ToString("##,#") + "km", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
//GUILayout.EndHorizontal();  
   
//GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
else GUILayout.Label(Tools.ConvertInterval(body.orbit.timeToPe), VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); else GUILayout.Label(Tools.ConvertInterval(body.orbit.timeToPe), VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
//GUILayout.EndHorizontal();  
   
//GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
else GUILayout.Label((body.orbit.semiMajorAxis / 1000).ToString("##,#") + "km", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); else GUILayout.Label((body.orbit.semiMajorAxis / 1000).ToString("##,#") + "km", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
//GUILayout.EndHorizontal();  
   
//GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
else GUILayout.Label(body.orbit.eccentricity.ToString("F4") + "", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); else GUILayout.Label(body.orbit.eccentricity.ToString("F4") + "", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
//GUILayout.EndHorizontal();  
   
//GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
else GUILayout.Label(Tools.ConvertInterval(body.orbit.period), VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); else GUILayout.Label(Tools.ConvertInterval(body.orbit.period), VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
//GUILayout.EndHorizontal();  
   
//GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
else GUILayout.Label(Tools.ConvertInterval(body.rotationPeriod), VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); else GUILayout.Label(Tools.ConvertInterval(body.rotationPeriod), VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
//GUILayout.EndHorizontal();  
   
//GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
else GUILayout.Label((body.orbit.orbitalSpeed / 1000).ToString("F2") + "km/s", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); else GUILayout.Label((body.orbit.orbitalSpeed / 1000).ToString("F2") + "km/s", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
//GUILayout.EndHorizontal();  
   
//GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
// Toadicus edit: convert mean anomaly into degrees. // Toadicus edit: convert mean anomaly into degrees.
if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
else GUILayout.Label((body.orbit.meanAnomaly * 180d / Math.PI).ToString("F3") + "°", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); else GUILayout.Label((body.orbit.meanAnomaly * 180d / Math.PI).ToString("F3") + "°", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
//GUILayout.EndHorizontal();  
   
//GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
else GUILayout.Label(body.orbit.trueAnomaly.ToString("F3") + "°", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); else GUILayout.Label(body.orbit.trueAnomaly.ToString("F3") + "°", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
//GUILayout.EndHorizontal();  
   
//GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
// Toadicus edit: convert eccentric anomaly into degrees. // Toadicus edit: convert eccentric anomaly into degrees.
if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
else GUILayout.Label((body.orbit.eccentricAnomaly * 180d / Math.PI).ToString("F3") + "°", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); else GUILayout.Label((body.orbit.eccentricAnomaly * 180d / Math.PI).ToString("F3") + "°", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
//GUILayout.EndHorizontal();  
   
//GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
else GUILayout.Label(body.orbit.inclination.ToString("F3") + "°", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); else GUILayout.Label(body.orbit.inclination.ToString("F3") + "°", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
//GUILayout.EndHorizontal();  
   
//GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
else GUILayout.Label(body.orbit.LAN.ToString("F3") + "°", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); else GUILayout.Label(body.orbit.LAN.ToString("F3") + "°", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
//GUILayout.EndHorizontal();  
   
//GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
else GUILayout.Label(body.orbit.argumentOfPeriapsis.ToString("F3") + "°", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); else GUILayout.Label(body.orbit.argumentOfPeriapsis.ToString("F3") + "°", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
//GUILayout.EndHorizontal();  
   
//GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
else else
{ {
string body_tidally_locked = "No"; string body_tidally_locked = "No";
if (body.tidallyLocked) body_tidally_locked = "Yes"; if (body.tidallyLocked) body_tidally_locked = "Yes";
GUILayout.Label(body_tidally_locked, VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); GUILayout.Label(body_tidally_locked, VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
} }
//GUILayout.EndHorizontal();  
} }
   
private void body_OP_show_physical_info(CelestialBody body) private void body_OP_show_physical_info(CelestialBody body)
{ {
//GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
GUILayout.Label((body.Radius / 1000).ToString("##,#") + "km", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); GUILayout.Label((body.Radius / 1000).ToString("##,#") + "km", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
//GUILayout.EndHorizontal();  
   
//GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
GUILayout.Label(((Math.Pow((body.Radius), 2) * 4 * Math.PI) / 1000).ToString("0.00e+00") + "km²", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); GUILayout.Label(((Math.Pow((body.Radius), 2) * 4 * Math.PI) / 1000).ToString("0.00e+00") + "km²", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
//GUILayout.EndHorizontal();  
   
//GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
// divide by 1000 to convert m to km // divide by 1000 to convert m to km
GUILayout.Label((((4d / 3) * Math.PI * Math.Pow(body.Radius, 3)) / 1000).ToString("0.00e+00") + "km³", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); GUILayout.Label((((4d / 3) * Math.PI * Math.Pow(body.Radius, 3)) / 1000).ToString("0.00e+00") + "km³", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
//GUILayout.Label(((4 / 3) * Math.PI * Math.Pow((vessel.mainBody.Radius / 1000), 3)).ToString(), right, GUILayout.ExpandWidth(true));  
//GUILayout.EndHorizontal();  
   
//GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
GUILayout.Label(body.Mass.ToString("0.00e+00") + "kg", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); GUILayout.Label(body.Mass.ToString("0.00e+00") + "kg", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
//GUILayout.EndHorizontal();  
   
double p = body.Mass / (Math.Pow(body.Radius, 3) * (4d / 3) * Math.PI); double p = body.Mass / (Math.Pow(body.Radius, 3) * (4d / 3) * Math.PI);
//GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
GUILayout.Label(p.ToString("##,#") + "kg/m³", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); GUILayout.Label(p.ToString("##,#") + "kg/m³", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
//GUILayout.EndHorizontal();  
   
//GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
if (body.bodyName == "Sun") GUILayout.Label(Tools.MuMech_ToSI(body.sphereOfInfluence), VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); if (body.bodyName == "Sun") GUILayout.Label(Tools.MuMech_ToSI(body.sphereOfInfluence), VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
else GUILayout.Label(Tools.MuMech_ToSI(body.sphereOfInfluence), VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); else GUILayout.Label(Tools.MuMech_ToSI(body.sphereOfInfluence), VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
//GUILayout.EndHorizontal();  
   
//GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
GUILayout.Label(body.orbitingBodies.Count.ToString(), VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); GUILayout.Label(body.orbitingBodies.Count.ToString(), VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
//GUILayout.EndHorizontal();  
   
//show # artificial satellites //show # artificial satellites
int num_art_sats = 0; int num_art_sats = 0;
foreach (Vessel v in FlightGlobals.Vessels) foreach (Vessel v in FlightGlobals.Vessels)
{ {
if (v.mainBody == body && v.situation.ToString() == "ORBITING") num_art_sats++; if (v.mainBody == body && v.situation.ToString() == "ORBITING") num_art_sats++;
} }
   
//GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
GUILayout.Label(num_art_sats.ToString(), VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); GUILayout.Label(num_art_sats.ToString(), VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
//GUILayout.EndHorizontal();  
   
double g_ASL = (VOID_Core.Constant_G * body.Mass) / Math.Pow(body.Radius, 2); double g_ASL = (VOID_Core.Constant_G * body.Mass) / Math.Pow(body.Radius, 2);
//GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
GUILayout.Label(Tools.MuMech_ToSI(g_ASL) + "m/s²", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); GUILayout.Label(Tools.MuMech_ToSI(g_ASL) + "m/s²", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
//GUILayout.EndHorizontal();  
  if (body.atmosphere)
//GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); {
GUILayout.Label("≈ " + Tools.MuMech_ToSI(body.maxAtmosphereAltitude) + "m", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); GUILayout.Label("≈ " + Tools.MuMech_ToSI(body.maxAtmosphereAltitude) + "m",
//GUILayout.EndHorizontal(); VOID_Core.Instance.LabelStyles["right"],
  GUILayout.ExpandWidth(true));
//GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));  
string O2 = "No"; string O2 = "No";
if (body.atmosphereContainsOxygen == true) O2 = "Yes"; if (body.atmosphereContainsOxygen == true) O2 = "Yes";
GUILayout.Label(O2, VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); GUILayout.Label(O2, VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
//GUILayout.EndHorizontal(); }
  else
//GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); {
  GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
  GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
  }
   
string ocean = "No"; string ocean = "No";
if (body.ocean == true) ocean = "Yes"; if (body.ocean == true) ocean = "Yes";
GUILayout.Label(ocean, VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true)); GUILayout.Label(ocean, VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
//GUILayout.EndHorizontal();  
} }
} }
} }
// //
// 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 Engineer.VesselSimulator;
  using KSP;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using KSP; using ToadicusTools;
using UnityEngine; using UnityEngine;
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.20"; protected string VoidVersion = "0.10.0";
   
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 - 32, 32f, 32f); protected VOID_SaveValue<Rect> VOIDIconPos = new Rect(Screen.width / 2 - 200, Screen.height - 32, 32f, 32f);
   
protected Texture2D VOIDIconTexture; protected Texture2D VOIDIconTexture;
protected string VOIDIconOnActivePath; protected string VOIDIconOnActivePath;
protected string VOIDIconOnInactivePath; protected string VOIDIconOnInactivePath;
protected string VOIDIconOffActivePath; protected string VOIDIconOffActivePath;
protected string VOIDIconOffInactivePath; protected string VOIDIconOffInactivePath;
   
protected bool VOIDIconLocked = true; protected bool VOIDIconLocked = true;
   
protected GUIStyle iconStyle; protected GUIStyle iconStyle;
   
protected int windowBaseID = -96518722; protected int windowBaseID = -96518722;
protected int _windowID = 0; protected int _windowID = 0;
   
protected bool GUIStylesLoaded = false; protected bool GUIStylesLoaded = false;
protected Dictionary<string, GUIStyle> _LabelStyles = new Dictionary<string, GUIStyle>(); protected Dictionary<string, GUIStyle> _LabelStyles = new Dictionary<string, GUIStyle>();
   
protected CelestialBody _Kerbin; protected CelestialBody _Kerbin;
   
[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;
   
// 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 int _skinIdx;
protected List<string> skinNames;  
  protected Dictionary<string, GUISkin> validSkins;
  protected 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" "PartTooltipSkin"
}; };
protected bool skinsLoaded = false; protected bool skinsLoaded = false;
   
public bool configDirty; public bool configDirty;
   
[AVOID_SaveValue("UseBlizzyToolbar")] [AVOID_SaveValue("UseBlizzyToolbar")]
protected VOID_SaveValue<bool> _UseToolbarManager; protected VOID_SaveValue<bool> _UseToolbarManager;
internal IButton ToolbarButton; internal IButton 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)
{ {
return AssetBase.GetGUISkin(this.defaultSkin); try
} {
return this.skin_list[this._skinName]; return this.validSkins[this._skinName];
  }
  catch
  {
  }
  }
   
  return AssetBase.GetGUISkin(this.defaultSkin);
} }
} }
   
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 FlightGlobals.Bodies; return FlightGlobals.Bodies;
} }
} }
   
public CelestialBody Kerbin public CelestialBody Kerbin
{ {
get get
{ {
if (this._Kerbin == null) if (this._Kerbin == null)
{ {
if (FlightGlobals.Bodies != null) if (FlightGlobals.Bodies != null)
{ {
this._Kerbin = FlightGlobals.Bodies.First(b => b.name == "Kerbin"); this._Kerbin = FlightGlobals.Bodies.First(b => b.name == "Kerbin");
} }
} }
   
return this._Kerbin; return this._Kerbin;
} }
} }
   
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 IconState powerState protected IconState powerState
{ {
get get
{ {
if (this.togglePower && this.powerAvailable) if (this.togglePower && this.powerAvailable)
{ {
return IconState.PowerOn; return IconState.PowerOn;
} }
else else
{ {
return IconState.PowerOff; return IconState.PowerOff;
} }
   
} }
} }
   
protected IconState activeState protected IconState activeState
{ {
get get
{ {
if (this.mainGuiMinimized) if (this.mainGuiMinimized)
{ {
return IconState.Inactive; return IconState.Inactive;
} }
else else
{ {
return IconState.Active; return IconState.Active;
} }
   
} }
} }
   
protected bool UseToolbarManager protected bool UseToolbarManager
{ {
get get
{ {
return _UseToolbarManager; return _UseToolbarManager;
} }
set set
{ {
if (this._UseToolbarManager == value) if (this._UseToolbarManager == value)
{ {
return; return;
} }
   
if (value == false && this.ToolbarButton != null) if (value == false && this.ToolbarButton != null)
{ {
this.ToolbarButton.Destroy(); this.ToolbarButton.Destroy();
this.ToolbarButton = null; this.ToolbarButton = null;
} }
if (value == true && this.ToolbarButton == null) if (value == true)
{ {
this.InitializeToolbarButton(); this.InitializeToolbarButton();
} }
   
this.SetIconTexture(this.powerState | this.activeState);  
   
_UseToolbarManager.value = value; _UseToolbarManager.value = value;
} }
} }
   
/* /*
* Methods * Methods
* */ * */
public override void DrawGUI() public override void DrawGUI()
{ {
this._windowID = this.windowBaseID; this._windowID = this.windowBaseID;
   
if (!this._modulesLoaded) if (!this._modulesLoaded)
{ {
this.LoadModulesOfType<IVOID_Module>(); this.LoadModulesOfType<IVOID_Module>();
} }
   
if (!this.skinsLoaded) if (!this.skinsLoaded)
{ {
this.LoadSkins(); this.LoadSkins();
} }
   
GUI.skin = this.Skin; GUI.skin = this.Skin;
   
if (!this.GUIStylesLoaded) if (!this.GUIStylesLoaded)
{ {
this.LoadGUIStyles(); this.LoadGUIStyles();
} }
   
if (!this.UseToolbarManager) if (!this.UseToolbarManager)
{ {
if (GUI.Button(VOIDIconPos, VOIDIconTexture, this.iconStyle) && this.VOIDIconLocked) if (GUI.Button(VOIDIconPos, VOIDIconTexture, this.iconStyle) && this.VOIDIconLocked)
{ {
this.ToggleMainWindow(); this.ToggleMainWindow();
} }
} }
else if (this.ToolbarButton == null) else if (this.ToolbarButton == null)
{ {
this.InitializeToolbarButton(); this.InitializeToolbarButton();
} }
   
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.Gravity = VOID_Core.Instance.vessel.mainBody.gravParameter /
Math.Pow(VOID_Core.Instance.vessel.Radius(), 2); Math.Pow(VOID_Core.Instance.vessel.Radius(), 2);
SimManager.Instance.TryStartSimulation(); SimManager.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()
{ {
bool newPowerState = this.powerAvailable; bool newPowerState = this.powerAvailable;
   
if (this.togglePower && this.consumeResource && if (this.togglePower && this.consumeResource &&
this.vessel.vesselType != VesselType.EVA && this.vessel.vesselType != VesselType.EVA &&
TimeWarp.deltaTime != 0) TimeWarp.deltaTime != 0)
{ {
float powerReceived = this.vessel.rootPart.RequestResource( float powerReceived = this.vessel.rootPart.RequestResource(
this.resourceName, this.resourceName,
this.resourceRate * TimeWarp.fixedDeltaTime this.resourceRate * TimeWarp.fixedDeltaTime
); );
   
if (powerReceived > 0) if (powerReceived > 0)
{ {
newPowerState = true; newPowerState = true;
} }
else else
{ {
newPowerState = false; newPowerState = false;
} }
   
if (this.powerAvailable != newPowerState) if (this.powerAvailable != newPowerState)
{ {
this.powerAvailable = newPowerState; this.powerAvailable = newPowerState;
this.SetIconTexture(this.powerState | this.activeState); this.SetIconTexture(this.powerState | this.activeState);
} }
} }
   
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();
} }
   
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 = string.Intern("ON"); string str = string.Intern("ON");
if (togglePower) if (togglePower)
str = string.Intern("OFF"); str = string.Intern("OFF");
if (GUILayout.Button("Power " + str)) if (GUILayout.Button("Power " + str))
{ {
togglePower.value = !togglePower; togglePower.value = !togglePower;
this.SetIconTexture(this.powerState | this.activeState); this.SetIconTexture(this.powerState | this.activeState);
} }
} }
   
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;  
   
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 If Available"); 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))  
{  
skinIdx = skinNames.IndexOf(this._skinName);  
}  
else if (skinNames.Contains(this.defaultSkin))  
{  
skinIdx = skinNames.IndexOf(this.defaultSkin);  
}  
else  
{  
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; this.GUIStylesLoaded = false;
skinIdx--; this._skinIdx--;
if (skinIdx < 0)  
skinIdx = skinNames.Count - 1;  
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: new this._skinIdx = {1} :: skin_list.Count = {2}", "{0}: new this._skinIdx = {1} :: skin_list.Count = {2}",
this.GetType().Name, this.GetType().Name,
this._skinName, this._skinName,
this.skin_list.Count this.validSkins.Count
)); ));
} }
   
_content.text = this.Skin.name; _content.text = this.Skin.name;
_content.tooltip = "Current skin"; _content.tooltip = "Current skin";
GUILayout.Label(_content, 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; this.GUIStylesLoaded = false;
skinIdx++; this._skinIdx++;
if (skinIdx >= skinNames.Count)  
skinIdx = 0;  
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: new this._skinIdx = {1} :: skin_list.Count = {2}", "{0}: new this._skinIdx = {1} :: skin_list.Count = {2}",
this.GetType().Name, this.GetType().Name,
this._skinName, this._skinName,
this.skin_list.Count this.validSkins.Count
)); ));
} }
   
if (this._skinName != skinNames[skinIdx]) this._skinIdx %= this.skinNames.Length;
{ if (this._skinIdx < 0)
this._skinName = skinNames[skinIdx]; {
  this._skinIdx += this.skinNames.Length;
  }
   
  if (this._skinName != skinNames[this._skinIdx])
  {
  this._skinName.value = skinNames[this._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");
} }
   
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) foreach (var voidType in types)
{ {
if (!HighLogic.LoadedSceneIsEditor && if (!HighLogic.LoadedSceneIsEditor &&
typeof(IVOID_EditorModule).IsAssignableFrom(voidType)) typeof(IVOID_EditorModule).IsAssignableFrom(voidType))
{ {
continue; continue;
} }
   
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( 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", string.Join("\n\t",
Resources.FindObjectsOfTypeAll(typeof(GUISkin)) Resources.FindObjectsOfTypeAll(typeof(GUISkin))
.Select(s => s.ToString()) .Select(s => s.ToString())
.ToArray() .ToArray()
) )
); );
   
this.skin_list = Resources.FindObjectsOfTypeAll(typeof(GUISkin)) this.validSkins = Resources.FindObjectsOfTypeAll(typeof(GUISkin))
.Where(s => !this.forbiddenSkins.Contains(s.name)) .Where(s => !this.forbiddenSkins.Contains(s.name))
.Select(s => s as GUISkin) .Select(s => s as GUISkin)
.GroupBy(s => s.name) .GroupBy(s => s.name)
.Select(g => g.First()) .Select(g => g.First())
.ToDictionary(s => s.name); .ToDictionary(s => s.name);
   
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: loaded {1} GUISkins.", "{0}: loaded {1} GUISkins.",
this.GetType().Name, this.GetType().Name,
this.skin_list.Count this.validSkins.Count
)); ));
   
this.skinNames = this.skin_list.Keys.ToList(); this.skinNames = this.validSkins.Keys.ToArray();
this.skinNames.Sort(); Array.Sort(this.skinNames);
   
if (this._skinName == null || !this.skinNames.Contains(this._skinName)) int defaultIdx = int.MinValue;
{  
this._skinName = this.defaultSkin; for (int i = 0; i < this.skinNames.Length; i++)
Tools.PostDebugMessage(string.Format( {
"{0}: resetting _skinIdx to default.", if (this.skinNames[i] == this._skinName)
this.GetType().Name {
)); this._skinIdx = i;
  }
  if (this.skinNames[i] == this.defaultSkin)
  {
  defaultIdx = i;
  }
  if (this._skinIdx != int.MinValue && defaultIdx != int.MinValue)
  {
  break;
  }
  }
   
  if (this._skinIdx == int.MinValue)
  {
  this._skinIdx = defaultIdx;
} }
   
Tools.PostDebugMessage(string.Format( 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 = new GUIStyle(GUI.skin.button);
this.iconStyle.padding = new RectOffset(0, 0, 0, 0); this.iconStyle.padding = new RectOffset(0, 0, 0, 0);
// this.iconStyle.margin = new RectOffset(0, 0, 0, 0); // this.iconStyle.margin = new RectOffset(0, 0, 0, 0);
// this.iconStyle.contentOffset = new Vector2(0, 0); // this.iconStyle.contentOffset = new Vector2(0, 0);
this.iconStyle.overflow = new RectOffset(0, 0, 0, 0); this.iconStyle.overflow = new RectOffset(0, 0, 0, 0);
// this.iconStyle.border = new RectOffset(0, 0, 0, 0); // this.iconStyle.border = new RectOffset(0, 0, 0, 0);
   
this.GUIStylesLoaded = true; this.GUIStylesLoaded = true;
} }
   
protected void LoadVesselTypes() protected void LoadVesselTypes()
{ {
this._allVesselTypes = Enum.GetValues(typeof(VesselType)).OfType<VesselType>().ToList(); this._allVesselTypes = Enum.GetValues(typeof(VesselType)).OfType<VesselType>().ToList();
this.vesselTypesLoaded = true; this.vesselTypesLoaded = true;
} }
   
protected void LoadBeforeUpdate() protected void LoadBeforeUpdate()
{ {
if (!this.vesselTypesLoaded) if (!this.vesselTypesLoaded)
{ {
this.LoadVesselTypes(); this.LoadVesselTypes();
} }
} }
   
protected void InitializeToolbarButton() protected void InitializeToolbarButton()
{ {
this.ToolbarButton = ToolbarManager.Instance.add(this.GetType().Name, "coreToggle"); this.ToolbarButton = ToolbarManager.Instance.add(this.VoidName, "coreToggle");
this.ToolbarButton.Text = this.VoidName; this.ToolbarButton.Text = this.VoidName;
this.SetIconTexture(this.powerState | this.activeState); this.SetIconTexture(this.powerState | this.activeState);
   
if (this is VOID_EditorCore) this.ToolbarButton.Visibility = new GameScenesVisibility(GameScenes.EDITOR, GameScenes.FLIGHT, GameScenes.SPH);
{  
this.ToolbarButton.Visibility = new GameScenesVisibility(GameScenes.EDITOR);  
}  
else  
{  
this.ToolbarButton.Visibility = new GameScenesVisibility(GameScenes.FLIGHT);  
}  
   
this.ToolbarButton.OnClick += this.ToolbarButton.OnClick +=
(e) => (e) =>
{ {
this.ToggleMainWindow(); this.ToggleMainWindow();
}; };
   
  Tools.PostDebugMessage(string.Format("{0}: Toolbar Button initialized.", this.GetType().Name));
} }
   
protected void ToggleMainWindow() protected void ToggleMainWindow()
{ {
this.mainGuiMinimized = !this.mainGuiMinimized; this.mainGuiMinimized = !this.mainGuiMinimized;
this.SetIconTexture(this.powerState | this.activeState); this.SetIconTexture(this.powerState | this.activeState);
} }
   
protected void SetIconTexture(IconState state) protected void SetIconTexture(IconState state)
{ {
switch (state) switch (state)
{ {
case (IconState.PowerOff | IconState.Inactive): case (IconState.PowerOff | IconState.Inactive):
this.SetIconTexture(this.VOIDIconOffInactivePath); this.SetIconTexture(this.VOIDIconOffInactivePath);
break; break;
case (IconState.PowerOff | IconState.Active): case (IconState.PowerOff | IconState.Active):
this.SetIconTexture(this.VOIDIconOffActivePath); this.SetIconTexture(this.VOIDIconOffActivePath);
break; break;
case (IconState.PowerOn | IconState.Inactive): case (IconState.PowerOn | IconState.Inactive):
this.SetIconTexture(this.VOIDIconOnInactivePath); this.SetIconTexture(this.VOIDIconOnInactivePath);
break; break;
case (IconState.PowerOn | IconState.Active): case (IconState.PowerOn | IconState.Active):
this.SetIconTexture(this.VOIDIconOnActivePath); this.SetIconTexture(this.VOIDIconOnActivePath);
break; break;
default: default:
throw new NotImplementedException(); throw new NotImplementedException();
} }
} }
   
protected void SetIconTexture(string texturePath) protected void SetIconTexture(string texturePath)
{ {
if (this.UseToolbarManager && this.ToolbarButton != null) if (this.ToolbarButton != null)
{ {
this.ToolbarButton.TexturePath = texturePath; this.ToolbarButton.TexturePath = texturePath;
} }
else  
{ this.VOIDIconTexture = GameDatabase.Instance.GetTexture(texturePath, false);
this.VOIDIconTexture = GameDatabase.Instance.GetTexture(texturePath, false);  
}  
} }
   
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;
} }
   
protected VOID_Core() protected VOID_Core()
{ {
this._Name = "VOID Core"; this._Name = "VOID Core";
   
this._Active.value = true; this._Active.value = true;
   
this._skinName = this.defaultSkin; this._skinName = this.defaultSkin;
  this._skinIdx = int.MinValue;
this.VOIDIconOnActivePath = "VOID/Textures/void_icon_light_glow";  
this.VOIDIconOnInactivePath = "VOID/Textures/void_icon_dark_glow"; this.VOIDIconOnInactivePath = "VOID/Textures/void_icon_light_glow";
this.VOIDIconOffActivePath = "VOID/Textures/void_icon_light"; this.VOIDIconOnActivePath = "VOID/Textures/void_icon_dark_glow";
this.VOIDIconOffInactivePath = "VOID/Textures/void_icon_dark"; this.VOIDIconOffInactivePath = "VOID/Textures/void_icon_light";
  this.VOIDIconOffActivePath = "VOID/Textures/void_icon_dark";
   
this.UseToolbarManager = false; this.UseToolbarManager = false;
   
this.LoadConfig(); this.LoadConfig();
   
this.SetIconTexture(this.powerState | this.activeState); this.SetIconTexture(this.powerState | this.activeState);
} }
   
protected enum IconState protected enum IconState
{ {
PowerOff = 1, PowerOff = 1,
PowerOn = 2, PowerOn = 2,
Inactive = 4, Inactive = 4,
Active = 8 Active = 8
} }
} }
   
  public static partial class VOID_Data
  {
  public static VOID_Core core
  {
  get
  {
  return VOID_Core.Instance;
  }
  }
   
  public static double KerbinGee
  {
  get
  {
  return core.Kerbin.gravParameter / Math.Pow(core.Kerbin.Radius, 2);
  }
  }
  }
} }
   
   
// //
// 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 ToadicusTools;
using UnityEngine; using UnityEngine;
   
namespace VOID namespace VOID
{ {
public class VOID_DataLogger : VOID_WindowModule, IVOID_BehaviorModule public class VOID_DataLogger : VOID_WindowModule, IVOID_BehaviorModule
{ {
/* /*
* Fields * Fields
* */ * */
protected bool stopwatch1_running; protected bool stopwatch1_running;
   
protected bool csv_logging; protected bool csv_logging;
protected bool first_write; protected bool first_write;
   
protected double stopwatch1; protected double stopwatch1;
   
protected string csv_log_interval_str; protected string csv_log_interval_str;
   
protected float csv_log_interval; protected float csv_log_interval;
   
protected double csvWriteTimer; protected double csvWriteTimer;
protected double csvCollectTimer; protected double csvCollectTimer;
   
protected List<string> csvList = new List<string>(); protected List<string> csvList = new List<string>();
   
/* /*
* Properties * Properties
* */ * */
   
   
/* /*
* Methods * Methods
* */ * */
public VOID_DataLogger() public VOID_DataLogger()
{ {
this._Name = "CSV Data Logger"; this._Name = "CSV Data Logger";
   
this.stopwatch1_running = false; this.stopwatch1_running = false;
   
this.csv_logging = false; this.csv_logging = false;
this.first_write = true; this.first_write = true;
   
this.stopwatch1 = 0; this.stopwatch1 = 0;
this.csv_log_interval_str = "0.5"; this.csv_log_interval_str = "0.5";
   
this.csvWriteTimer = 0; this.csvWriteTimer = 0;
this.csvCollectTimer = 0; this.csvCollectTimer = 0;
   
this.WindowPos.x = Screen.width - 520; this.WindowPos.x = Screen.width - 520;
this.WindowPos.y = 85; this.WindowPos.y = 85;
} }
   
public override void ModuleWindow(int _) public override void ModuleWindow(int _)
{ {
GUIStyle txt_white = new GUIStyle(GUI.skin.label); GUIStyle txt_white = new GUIStyle(GUI.skin.label);
txt_white.normal.textColor = txt_white.focused.textColor = Color.white; txt_white.normal.textColor = txt_white.focused.textColor = Color.white;
txt_white.alignment = TextAnchor.UpperRight; txt_white.alignment = TextAnchor.UpperRight;
GUIStyle txt_green = new GUIStyle(GUI.skin.label); GUIStyle txt_green = new GUIStyle(GUI.skin.label);
txt_green.normal.textColor = txt_green.focused.textColor = Color.green; txt_green.normal.textColor = txt_green.focused.textColor = Color.green;
txt_green.alignment = TextAnchor.UpperRight; txt_green.alignment = TextAnchor.UpperRight;
GUIStyle txt_yellow = new GUIStyle(GUI.skin.label); GUIStyle txt_yellow = new GUIStyle(GUI.skin.label);
txt_yellow.normal.textColor = txt_yellow.focused.textColor = Color.yellow; txt_yellow.normal.textColor = txt_yellow.focused.textColor = Color.yellow;
txt_yellow.alignment = TextAnchor.UpperRight; txt_yellow.alignment = TextAnchor.UpperRight;
   
GUILayout.BeginVertical(); GUILayout.BeginVertical();
   
GUILayout.Label("System time: " + DateTime.Now.ToString("HH:mm:ss")); GUILayout.Label("System time: " + DateTime.Now.ToString("HH:mm:ss"));
GUILayout.Label(Tools.ConvertInterval(stopwatch1)); GUILayout.Label(Tools.ConvertInterval(stopwatch1));
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
if (GUILayout.Button("Start")) if (GUILayout.Button("Start"))
{ {
if (stopwatch1_running == false) stopwatch1_running = true; if (stopwatch1_running == false) stopwatch1_running = true;
} }
if (GUILayout.Button("Stop")) if (GUILayout.Button("Stop"))
{ {
if (stopwatch1_running == true) stopwatch1_running = false; if (stopwatch1_running == true) stopwatch1_running = false;
} }
if (GUILayout.Button("Reset")) if (GUILayout.Button("Reset"))
{ {
if (stopwatch1_running == true) stopwatch1_running = false; if (stopwatch1_running == true) stopwatch1_running = false;
stopwatch1 = 0; stopwatch1 = 0;
} }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUIStyle label_style = txt_white; GUIStyle label_style = txt_white;
string log_label = "Inactive"; string log_label = "Inactive";
if (csv_logging && vessel.situation.ToString() == "PRELAUNCH") if (csv_logging && vessel.situation.ToString() == "PRELAUNCH")
{ {
log_label = "Awaiting launch"; log_label = "Awaiting launch";
label_style = txt_yellow; label_style = txt_yellow;
} }
if (csv_logging && vessel.situation.ToString() != "PRELAUNCH") if (csv_logging && vessel.situation.ToString() != "PRELAUNCH")
{ {
log_label = "Active"; log_label = "Active";
label_style = txt_green; label_style = txt_green;
} }
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
csv_logging = GUILayout.Toggle(csv_logging, "Data logging: ", GUILayout.ExpandWidth(false)); csv_logging = GUILayout.Toggle(csv_logging, "Data logging: ", GUILayout.ExpandWidth(false));
GUILayout.Label(log_label, label_style, GUILayout.ExpandWidth(true)); GUILayout.Label(log_label, label_style, GUILayout.ExpandWidth(true));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Interval: ", GUILayout.ExpandWidth(false)); GUILayout.Label("Interval: ", GUILayout.ExpandWidth(false));
csv_log_interval_str = GUILayout.TextField(csv_log_interval_str, GUILayout.ExpandWidth(true)); csv_log_interval_str = GUILayout.TextField(csv_log_interval_str, GUILayout.ExpandWidth(true));
GUILayout.Label("s", GUILayout.ExpandWidth(false)); GUILayout.Label("s", GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
float new_log_interval; float new_log_interval;
if (Single.TryParse(csv_log_interval_str, out new_log_interval)) csv_log_interval = new_log_interval; if (Single.TryParse(csv_log_interval_str, out new_log_interval)) csv_log_interval = new_log_interval;
   
GUILayout.EndVertical(); GUILayout.EndVertical();
GUI.DragWindow(); GUI.DragWindow();
} }
   
public void Update() public void Update()
{ {
// CSV Logging // CSV Logging
// from ISA MapSat // from ISA MapSat
if (csv_logging) if (csv_logging)
{ {
//data logging is on //data logging is on
//increment timers //increment timers
csvWriteTimer += Time.deltaTime; csvWriteTimer += Time.deltaTime;
csvCollectTimer += Time.deltaTime; csvCollectTimer += Time.deltaTime;
   
if (csvCollectTimer >= csv_log_interval && vessel.situation != Vessel.Situations.PRELAUNCH) if (csvCollectTimer >= csv_log_interval && vessel.situation != Vessel.Situations.PRELAUNCH)
{ {
//data logging is on, vessel is not prelaunch, and interval has passed //data logging is on, vessel is not prelaunch, and interval has passed
//write a line to the list //write a line to the list
line_to_csvList(); //write to the csv line_to_csvList(); //write to the csv
} }
   
if (csvList.Count != 0 && csvWriteTimer >= 15f) if (csvList.Count != 0 && csvWriteTimer >= 15f)
{ {
// csvList is not empty and interval between writings to file has elapsed // csvList is not empty and interval between writings to file has elapsed
//write it //write it
string[] csvData; string[] csvData;
csvData = (string[])csvList.ToArray(); csvData = (string[])csvList.ToArray();
Innsewerants_writeData(csvData); Innsewerants_writeData(csvData);
csvList.Clear(); csvList.Clear();
csvWriteTimer = 0f; csvWriteTimer = 0f;
} }
} }
else else
{ {
//data logging is off //data logging is off
//reset any timers and clear anything from csvList //reset any timers and clear anything from csvList
csvWriteTimer = 0f; csvWriteTimer = 0f;
csvCollectTimer = 0f; csvCollectTimer = 0f;
if (csvList.Count > 0) csvList.Clear(); if (csvList.Count > 0) csvList.Clear();
} }
   
if (stopwatch1_running) if (stopwatch1_running)
{ {
stopwatch1 += Time.deltaTime; stopwatch1 += Time.deltaTime;
} }
} }
   
public void FixedUpdate() {} public void FixedUpdate() {}
   
private void Innsewerants_writeData(string[] csvArray) private void Innsewerants_writeData(string[] csvArray)
{ {
var efile = KSP.IO.File.AppendText<VOID_Core>(vessel.vesselName + "_data.csv", null); var efile = KSP.IO.File.AppendText<VOID_Core>(vessel.vesselName + "_data.csv", null);
foreach (string line in csvArray) foreach (string line in csvArray)
{ {
efile.Write(line); efile.Write(line);
} }
efile.Close(); efile.Close();
} }
   
private void line_to_csvList() private void line_to_csvList()
{ {
//called if logging is on and interval has passed //called if logging is on and interval has passed
//writes one line to the csvList //writes one line to the csvList
   
string line = ""; string line = "";
if (first_write && !KSP.IO.File.Exists<VOID_Core>(vessel.vesselName + "_data.csv", null)) if (first_write && !KSP.IO.File.Exists<VOID_Core>(vessel.vesselName + "_data.csv", null))
{ {
first_write = false; first_write = false;
line += "Mission Elapsed Time (s);Altitude ASL (m);Altitude above terrain (m);Orbital Velocity (m/s);Surface Velocity (m/s);Vertical Speed (m/s);Horizontal Speed (m/s);Gee Force (gees);Temperature (°C);Gravity (m/s²);Atmosphere Density (g/m³);\n"; line += "Mission Elapsed Time (s);Altitude ASL (m);Altitude above terrain (m);Orbital Velocity (m/s);Surface Velocity (m/s);Vertical Speed (m/s);Horizontal Speed (m/s);Gee Force (gees);Temperature (°C);Gravity (m/s²);Atmosphere Density (g/m³);\n";
} }
//Mission time //Mission time
line += vessel.missionTime.ToString("F3") + ";"; line += vessel.missionTime.ToString("F3") + ";";
//Altitude ASL //Altitude ASL
line += vessel.orbit.altitude.ToString("F3") + ";"; line += vessel.orbit.altitude.ToString("F3") + ";";
//Altitude (true) //Altitude (true)
double alt_true = vessel.orbit.altitude - vessel.terrainAltitude; double alt_true = vessel.orbit.altitude - vessel.terrainAltitude;
if (vessel.terrainAltitude < 0) alt_true = vessel.orbit.altitude; if (vessel.terrainAltitude < 0) alt_true = vessel.orbit.altitude;
line += alt_true.ToString("F3") + ";"; line += alt_true.ToString("F3") + ";";
//Orbital velocity //Orbital velocity
line += vessel.orbit.vel.magnitude.ToString("F3") + ";"; line += vessel.orbit.vel.magnitude.ToString("F3") + ";";
//surface velocity //surface velocity
line += vessel.srf_velocity.magnitude.ToString("F3") + ";"; line += vessel.srf_velocity.magnitude.ToString("F3") + ";";
//vertical speed //vertical speed
line += vessel.verticalSpeed.ToString("F3") + ";"; line += vessel.verticalSpeed.ToString("F3") + ";";
//horizontal speed //horizontal speed
line += vessel.horizontalSrfSpeed.ToString("F3") + ";"; line += vessel.horizontalSrfSpeed.ToString("F3") + ";";
//gee force //gee force
line += vessel.geeForce.ToString("F3") + ";"; line += vessel.geeForce.ToString("F3") + ";";
//temperature //temperature
line += vessel.flightIntegrator.getExternalTemperature().ToString("F2") + ";"; line += vessel.flightIntegrator.getExternalTemperature().ToString("F2") + ";";
//gravity //gravity
double r_vessel = vessel.mainBody.Radius + vessel.mainBody.GetAltitude(vessel.findWorldCenterOfMass()); 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); double g_vessel = (VOID_Core.Constant_G * vessel.mainBody.Mass) / Math.Pow(r_vessel, 2);
line += g_vessel.ToString("F3") + ";"; line += g_vessel.ToString("F3") + ";";
//atm density //atm density
line += (vessel.atmDensity * 1000).ToString("F3") + ";"; line += (vessel.atmDensity * 1000).ToString("F3") + ";";
line += "\n"; line += "\n";
if (csvList.Contains(line) == false) csvList.Add(line); if (csvList.Contains(line) == false) csvList.Add(line);
csvCollectTimer = 0f; csvCollectTimer = 0f;
} }
} }
} }
// //
// VOID_DataValue.cs // VOID_DataValue.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 ToadicusTools;
using UnityEngine; using UnityEngine;
   
namespace VOID namespace VOID
{ {
public interface IVOID_DataValue public interface IVOID_DataValue
{ {
void Refresh(); void Refresh();
string ValueUnitString(); string ValueUnitString();
void DoGUIHorizontal(); void DoGUIHorizontal();
} }
   
public class VOID_DataValue<T> : IVOID_DataValue public class VOID_DataValue<T> : IVOID_DataValue
{ {
/* /*
* Static Members * Static Members
* */ * */
public static implicit operator T(VOID_DataValue<T> v) public static implicit operator T(VOID_DataValue<T> v)
{ {
return (T)v.Value; return (T)v.Value;
} }
   
/* /*
* Instance Members * Instance Members
* */ * */
/* /*
* Fields * Fields
* */ * */
protected T cache; protected T cache;
protected Func<T> ValueFunc; protected Func<T> ValueFunc;
  protected float lastUpdate;
   
/* /*
* Properties * Properties
* */ * */
public string Label { get; protected set; } public string Label { get; protected set; }
public string Units { get; protected set; } public string Units { get; protected set; }
   
public T Value { public T Value
get { {
  get
  {
  if (
  (VOID_Core.Instance.updateTimer - this.lastUpdate > VOID_Core.Instance.updatePeriod) ||
  (this.lastUpdate > VOID_Core.Instance.updateTimer)
  )
  {
  this.Refresh();
  }
return (T)this.cache; return (T)this.cache;
} }
} }
   
/* /*
* Methods * Methods
* */ * */
public VOID_DataValue(string Label, Func<T> ValueFunc, string Units = "") public VOID_DataValue(string Label, Func<T> ValueFunc, string Units = "")
{ {
this.Label = Label; this.Label = Label;
this.Units = Units; this.Units = Units;
this.ValueFunc = ValueFunc; this.ValueFunc = ValueFunc;
  this.lastUpdate = 0;
} }
   
public void Refresh() public void Refresh()
{ {
this.cache = this.ValueFunc.Invoke (); this.cache = this.ValueFunc.Invoke ();
  this.lastUpdate = VOID_Core.Instance.updateTimer;
} }
   
public T GetFreshValue() public T GetFreshValue()
{ {
this.Refresh (); this.Refresh ();
return (T)this.cache; return (T)this.cache;
} }
   
public string ValueUnitString() { public string ValueUnitString() {
return this.Value.ToString() + this.Units; return this.Value.ToString() + this.Units;
} }
   
public virtual void DoGUIHorizontal() public virtual void DoGUIHorizontal()
{ {
GUILayout.BeginHorizontal (GUILayout.ExpandWidth (true)); GUILayout.BeginHorizontal (GUILayout.ExpandWidth (true));
GUILayout.Label (this.Label + ":"); GUILayout.Label (this.Label + ":");
GUILayout.FlexibleSpace (); GUILayout.FlexibleSpace ();
GUILayout.Label (this.ValueUnitString(), GUILayout.ExpandWidth (false)); GUILayout.Label (this.ValueUnitString(), GUILayout.ExpandWidth (false));
GUILayout.EndHorizontal (); GUILayout.EndHorizontal ();
} }
   
public override string ToString() public override string ToString()
{ {
return string.Format ( return string.Format (
"{0}: {1}{2}", "{0}: {1}{2}",
this.Label, this.Label,
this.Value.ToString (), this.Value.ToString (),
this.Units this.Units
); );
} }
} }
   
internal interface IVOID_NumericValue public abstract class VOID_NumValue<T> : VOID_DataValue<T>
{ where T : IFormattable, IConvertible, IComparable
double ToDouble(); {
string ToString(string format); public static implicit operator Double(VOID_NumValue<T> v)
string ToSIString(int digits, int MinMagnitude, int MaxMagnitude); {
} return v.ToDouble();
  }
public abstract class VOID_NumValue<T> : VOID_DataValue<T>, IVOID_NumericValue  
{ public static implicit operator Int32(VOID_NumValue<T> v)
public VOID_NumValue(string Label, Func<T> ValueFunc, string Units = "") : base(Label, ValueFunc, Units) {} {
  return v.ToInt32();
public abstract double ToDouble(); }
public abstract string ToString(string Format);  
public abstract string ToSIString(int digits = 3, int MinMagnitude = 0, int MaxMagnitude = int.MaxValue);  
  public static implicit operator Single(VOID_NumValue<T> v)
public abstract string ValueUnitString(string format); {
  return v.ToSingle();
  }
   
   
  protected IFormatProvider formatProvider;
   
  public VOID_NumValue(string Label, Func<T> ValueFunc, string Units = "") : base(Label, ValueFunc, Units)
  {
  this.formatProvider = System.Globalization.CultureInfo.CurrentUICulture;
  }
   
  public virtual double ToDouble(IFormatProvider provider)
  {
  return this.Value.ToDouble(provider);
  }
   
  public virtual double ToDouble()
  {
  return this.ToDouble(this.formatProvider);
  }
   
  public virtual int ToInt32(IFormatProvider provider)
  {
  return this.Value.ToInt32(provider);
  }
   
  public virtual int ToInt32()
  {
  return this.ToInt32(this.formatProvider);
  }
   
  public virtual float ToSingle(IFormatProvider provider)
  {
  return this.Value.ToSingle(provider);
  }
   
  public virtual float ToSingle()
  {
  return this.ToSingle(this.formatProvider);
  }
   
  public virtual string ToString(string Format)
  {
  return string.Format (
  "{0}: {1}{2}",
  this.Label,
  this.Value.ToString(Format, this.formatProvider),
  this.Units
  );
  }
   
  public virtual string ToSIString(int digits = 3, int MinMagnitude = 0, int MaxMagnitude = int.MaxValue)
  {
  return string.Format (
  "{0}{1}",
  Tools.MuMech_ToSI (this, digits, MinMagnitude, MaxMagnitude),
  this.Units
  );
  }
   
  public virtual string ValueUnitString(string format)
  {
  return this.Value.ToString(format, this.formatProvider) + this.Units;
  }
public virtual string ValueUnitString(int digits) { public virtual string ValueUnitString(int digits) {
return Tools.MuMech_ToSI(this.ToDouble(), digits) + this.Units; return Tools.MuMech_ToSI(this, digits) + this.Units;
} }
   
public virtual string ValueUnitString(int digits, int MinMagnitude, int MaxMagnitude) public virtual string ValueUnitString(int digits, int MinMagnitude, int MaxMagnitude)
{ {
return Tools.MuMech_ToSI(this.ToDouble(), digits, MinMagnitude, MaxMagnitude) + this.Units; return Tools.MuMech_ToSI(this, digits, MinMagnitude, MaxMagnitude) + this.Units;
} }
   
public virtual void DoGUIHorizontal(string format) public virtual void DoGUIHorizontal(string format)
{ {
GUILayout.BeginHorizontal (GUILayout.ExpandWidth (true)); GUILayout.BeginHorizontal (GUILayout.ExpandWidth (true));
GUILayout.Label (this.Label + ":"); GUILayout.Label (this.Label + ":");
GUILayout.FlexibleSpace (); GUILayout.FlexibleSpace ();
GUILayout.Label (this.ValueUnitString(format), GUILayout.ExpandWidth (false)); GUILayout.Label (this.ValueUnitString(format), GUILayout.ExpandWidth (false));
GUILayout.EndHorizontal (); GUILayout.EndHorizontal ();
} }
   
public virtual int DoGUIHorizontal(int digits, bool precisionButton = true) public virtual int DoGUIHorizontal(int digits, bool precisionButton = true)
{ {
if (precisionButton) if (precisionButton)
{ {
return this.DoGUIHorizontalPrec(digits); return this.DoGUIHorizontalPrec(digits);
} }
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label(this.Label + ":", GUILayout.ExpandWidth(true)); GUILayout.Label(this.Label + ":", GUILayout.ExpandWidth(true));
GUILayout.FlexibleSpace(); GUILayout.FlexibleSpace();
GUILayout.Label(this.ValueUnitString(digits), GUILayout.ExpandWidth(false)); GUILayout.Label(this.ValueUnitString(digits), GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
return digits; return digits;
} }
   
public virtual int DoGUIHorizontalPrec(int digits) public virtual int DoGUIHorizontalPrec(int digits)
{ {
float magnitude; double magnitude;
float magLimit; double magLimit;
   
magnitude = (float)Math.Log10(Math.Abs(this.ToDouble())); magnitude = Math.Log10(Math.Abs((double)this));
   
magLimit = Mathf.Max(magnitude, 6f); magLimit = Math.Max(Math.Abs(magnitude), 3d) + 3d;
magLimit = Mathf.Round((float)Math.Ceiling(magLimit / 3f) * 3f); magLimit = Math.Round(Math.Ceiling(magLimit / 3f)) * 3d;
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label(this.Label + "ⁱ:", GUILayout.ExpandWidth(true)); GUILayout.Label(this.Label + "ⁱ:", GUILayout.ExpandWidth(true));
GUILayout.FlexibleSpace(); GUILayout.FlexibleSpace();
   
GUILayout.Label(this.ValueUnitString(3, int.MinValue, (int)magnitude - digits), GUILayout.ExpandWidth(false)); if (magnitude >= 0)
  {
  GUILayout.Label(this.ValueUnitString(3, int.MinValue, (int)magnitude - digits), GUILayout.ExpandWidth(false));
  }
  else
  {
  GUILayout.Label(this.ValueUnitString(3, (int)magnitude + digits, int.MaxValue), GUILayout.ExpandWidth(false));
  }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
if (Event.current.type == EventType.mouseUp) if (Event.current.type == EventType.mouseUp)
{ {
Rect lastRect = GUILayoutUtility.GetLastRect(); Rect lastRect = GUILayoutUtility.GetLastRect();
if (lastRect.Contains(Event.current.mousePosition)) if (lastRect.Contains(Event.current.mousePosition))
{ {
  Tools.PostDebugMessage(string.Format("{0}: Changing digits from {1} within magLimit {2}.",
  this.GetType().Name,
  digits,
  magLimit));
   
if (Event.current.button == 0) if (Event.current.button == 0)
{ {
digits = (digits + 3) % (int)magLimit; digits = (digits + 3) % (int)magLimit;
} }
else if (Event.current.button == 1) else if (Event.current.button == 1)
{ {
digits = (digits - 3) % (int)magLimit; digits = (digits - 3) % (int)magLimit;
if (digits < 0)  
{  
digits = (int)magLimit - 3;  
}  
} }
   
  if (digits < 0)
  {
  digits += (int)magLimit;
  }
   
  Tools.PostDebugMessage(string.Format("{0}: Changed digits to {1}." +
  "\n\tNew minMagnitude: {2}, maxMagnitude: {3}" +
  "\n\tMagnitude: {4}",
  this.GetType().Name,
  digits,
  magnitude >= 0 ? int.MinValue : (int)magnitude - 4 + digits,
  magnitude >= 0 ? (int)magnitude - digits : int.MaxValue,
  magnitude
  ));
} }
} }
   
return digits; return digits;
} }
} }
   
public class VOID_DoubleValue : VOID_NumValue<double>, IVOID_NumericValue public class VOID_DoubleValue : VOID_NumValue<double>
{ {
public VOID_DoubleValue(string Label, Func<double> ValueFunc, string Units) : base(Label, ValueFunc, Units) {} public VOID_DoubleValue(string Label, Func<double> ValueFunc, string Units) : base(Label, ValueFunc, Units) {}
  }
public override double ToDouble ()  
{ public class VOID_FloatValue : VOID_NumValue<float>
return this.Value;  
}  
   
public override string ToString(string format)  
{  
return string.Format (  
"{0}: {1}{2}",  
this.Label,  
this.Value.ToString (format),  
this.Units  
);  
}  
   
public override string ValueUnitString(string format) {  
return this.Value.ToString(format) + this.Units;  
}  
   
public override string ToSIString(int digits = 3, int MinMagnitude = 0, int MaxMagnitude = int.MaxValue)  
{  
return string.Format (  
"{0}{1}",  
Tools.MuMech_ToSI (this.Value, digits, MinMagnitude, MaxMagnitude),  
this.Units  
);  
}  
}  
public class VOID_FloatValue : VOID_NumValue<float>, IVOID_NumericValue  
{ {
public VOID_FloatValue(string Label, Func<float> ValueFunc, string Units) : base(Label, ValueFunc, Units) {} public VOID_FloatValue(string Label, Func<float> ValueFunc, string Units) : base(Label, ValueFunc, Units) {}
  }
public override double ToDouble ()  
{ public class VOID_IntValue : VOID_NumValue<int>
return (double)this.Value;  
}  
   
public override string ValueUnitString(string format) {  
return this.Value.ToString(format) + this.Units;  
}  
   
public override string ToString(string format)  
{  
return string.Format (  
"{0}: {1}{2}",  
this.Label,  
this.Value.ToString (format),  
this.Units  
);  
}  
   
public override string ToSIString(int digits = 3, int MinMagnitude = 0, int MaxMagnitude = int.MaxValue)  
{  
return string.Format (  
"{0}{1}",  
Tools.MuMech_ToSI ((double)this.Value, digits, MinMagnitude, MaxMagnitude),  
this.Units  
);  
}  
}  
public class VOID_IntValue : VOID_NumValue<int>, IVOID_NumericValue  
{ {
public VOID_IntValue(string Label, Func<int> ValueFunc, string Units) : base(Label, ValueFunc, Units) {} public VOID_IntValue(string Label, Func<int> ValueFunc, string Units) : base(Label, ValueFunc, Units) {}
  }
public override double ToDouble ()  
{  
return (double)this.Value;  
}  
   
public override string ValueUnitString(string format) {  
return this.Value.ToString(format) + this.Units;  
}  
   
public override string ToString(string format)  
{  
return string.Format (  
"{0}: {1}{2}",  
this.Label,  
this.Value.ToString (format),  
this.Units  
);  
}  
   
public override string ToSIString(int digits = 3, int MinMagnitude = 0, int MaxMagnitude = int.MaxValue)  
{  
return string.Format (  
"{0}{1}",  
Tools.MuMech_ToSI ((double)this.Value, digits, MinMagnitude, MaxMagnitude),  
this.Units  
);  
}  
}  
   
   
public class VOID_StrValue : VOID_DataValue<string> public class VOID_StrValue : VOID_DataValue<string>
{ {
public VOID_StrValue(string Label, Func<string> ValueFunc) : base(Label, ValueFunc, "") {} public VOID_StrValue(string Label, Func<string> ValueFunc) : base(Label, ValueFunc, "") {}
} }
} }
   
   
// //
// VOID_EditorCore.cs // VOID_EditorCore.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.Linq;
  using ToadicusTools;
using UnityEngine; using UnityEngine;
   
namespace VOID namespace VOID
{ {
public class VOID_EditorCore : VOID_Core public class VOID_EditorCore : VOID_Core
{ {
/* /*
* Static Members * Static Members
* */ * */
protected new static bool _initialized = false; protected new static bool _initialized = false;
public new static bool Initialized public new static bool Initialized
{ {
get get
{ {
return _initialized; return _initialized;
} }
} }
   
protected new static VOID_EditorCore _instance; protected new static VOID_EditorCore _instance;
public new static VOID_EditorCore Instance public new static VOID_EditorCore Instance
{ {
get get
{ {
if (_instance == null) if (_instance == null)
{ {
_instance = new VOID_EditorCore(); _instance = new VOID_EditorCore();
_initialized = true; _initialized = true;
} }
return _instance; return _instance;
} }
} }
   
public new static void Reset() public new static void Reset()
{ {
if (_initialized) if (_initialized)
{ {
_instance.StopGUI(); _instance.StopGUI();
_instance = null; _instance = null;
_initialized = false; _initialized = false;
} }
} }
   
public VOID_EditorCore() : base() public VOID_EditorCore() : base()
{ {
this._Name = "VOID Editor Core"; this._Name = "VOID Editor Core";
} }
   
public new void OnGUI() {} public new void OnGUI() {}
   
public override void DrawGUI() public override void DrawGUI()
{ {
if (!this._modulesLoaded) if (!this._modulesLoaded)
{ {
this.LoadModulesOfType<IVOID_EditorModule>(); this.LoadModulesOfType<IVOID_EditorModule>();
} }
   
Rect _iconPos = Tools.DockToWindow (this.VOIDIconPos, this.mainWindowPos); Rect _iconPos = Tools.DockToWindow (this.VOIDIconPos, this.mainWindowPos);
   
_iconPos = Tools.ClampRectToScreen (_iconPos, (int)_iconPos.width, (int)_iconPos.height); _iconPos = Tools.ClampRectToScreen (_iconPos, (int)_iconPos.width, (int)_iconPos.height);
   
if (_iconPos != this.VOIDIconPos) if (_iconPos != this.VOIDIconPos)
{ {
this.VOIDIconPos = _iconPos; this.VOIDIconPos = _iconPos;
} }
   
base.DrawGUI(); base.DrawGUI();
} }
   
public new void Update() public new void Update()
{ {
foreach (IVOID_EditorModule module in this.Modules) foreach (IVOID_EditorModule module in this.Modules)
{ {
if (EditorLogic.startPod == null) if (EditorLogic.startPod == null)
{ {
module.StopGUI(); module.StopGUI();
continue; continue;
} }
if (HighLogic.LoadedSceneIsEditor && module.toggleActive && EditorLogic.SortedShipList.Any()) if (HighLogic.LoadedSceneIsEditor && module.toggleActive && EditorLogic.SortedShipList.Any())
{ {
module.StartGUI(); module.StartGUI();
} }
if (!HighLogic.LoadedSceneIsEditor || !module.toggleActive || !EditorLogic.SortedShipList.Any()) if (!HighLogic.LoadedSceneIsEditor || !module.toggleActive || !EditorLogic.SortedShipList.Any())
{ {
module.StopGUI(); module.StopGUI();
} }
} }
   
if (EditorLogic.startPod == null || !HighLogic.LoadedSceneIsEditor) if (EditorLogic.startPod == null || !HighLogic.LoadedSceneIsEditor)
{ {
this.StopGUI(); this.StopGUI();
return; return;
} }
else if (!this.guiRunning && HighLogic.LoadedSceneIsEditor) else if (!this.guiRunning && HighLogic.LoadedSceneIsEditor)
{ {
this.StartGUI(); this.StartGUI();
} }
   
if (EditorLogic.SortedShipList.Count > 0) if (EditorLogic.SortedShipList.Count > 0)
{ {
SimManager.Instance.Gravity = 9.08665; SimManager.Gravity = VOID_Data.KerbinGee;
SimManager.Instance.TryStartSimulation(); SimManager.TryStartSimulation();
} }
   
this.CheckAndSave (); this.CheckAndSave ();
} }
   
public new void FixedUpdate() {} public new void FixedUpdate() {}
} }
} }
   
   
// //
// 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.Linq;
using System.Text; using System.Text;
  using ToadicusTools;
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; 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 protected EditorVesselOverlays vesselOverlays
{ {
get get
{ {
if (this._vesselOverlays == null) if (this._vesselOverlays == null)
{ {
this._vesselOverlays = (EditorVesselOverlays)Resources this._vesselOverlays = (EditorVesselOverlays)Resources
.FindObjectsOfTypeAll(typeof(EditorVesselOverlays)) .FindObjectsOfTypeAll(typeof(EditorVesselOverlays))
.FirstOrDefault(); .FirstOrDefault();
} }
   
return this._vesselOverlays; return this._vesselOverlays;
} }
} }
   
protected EditorMarker_CoM CoMmarker protected EditorMarker_CoM CoMmarker
{ {
get get
{ {
if (this.vesselOverlays == null) if (this.vesselOverlays == null)
{ {
return null; return null;
} }
   
return this.vesselOverlays.CoMmarker; return this.vesselOverlays.CoMmarker;
} }
} }
   
protected EditorMarker_CoT CoTmarker protected EditorMarker_CoT CoTmarker
{ {
get get
{ {
if (this.vesselOverlays == null) if (this.vesselOverlays == null)
{ {
return null; return null;
} }
   
return this.vesselOverlays.CoTmarker; 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.RequestSimulation();
   
if (SimManager.Instance.LastStage == null) if (SimManager.LastStage == null)
{ {
return; return;
} }
   
float hudLeft; float hudLeft;
StringBuilder hudString; 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(); 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("Total Mass: ");
hudString.Append(SimManager.Instance.LastStage.totalMass.ToString("F3")); hudString.Append(SimManager.LastStage.totalMass.ToString("F3"));
hudString.Append('t'); hudString.Append('t');
   
hudString.Append(' '); hudString.Append(' ');
   
hudString.Append("Part Count: "); hudString.Append("Part Count: ");
hudString.Append(EditorLogic.SortedShipList.Count); hudString.Append(EditorLogic.SortedShipList.Count);
   
hudString.Append('\n'); hudString.Append('\n');
   
hudString.Append("Total Delta-V: "); hudString.Append("Total Delta-V: ");
hudString.Append(Tools.MuMech_ToSI(SimManager.Instance.LastStage.totalDeltaV)); hudString.Append(Tools.MuMech_ToSI(SimManager.LastStage.totalDeltaV));
hudString.Append("m/s"); hudString.Append("m/s");
   
hudString.Append('\n'); hudString.Append('\n');
   
hudString.Append("Bottom Stage Delta-V"); hudString.Append("Bottom Stage Delta-V");
hudString.Append(Tools.MuMech_ToSI(SimManager.Instance.LastStage.deltaV)); hudString.Append(Tools.MuMech_ToSI(SimManager.LastStage.deltaV));
hudString.Append("m/s"); hudString.Append("m/s");
   
hudString.Append('\n'); hudString.Append('\n');
   
hudString.Append("Bottom Stage T/W Ratio: "); hudString.Append("Bottom Stage T/W Ratio: ");
hudString.Append(SimManager.Instance.LastStage.thrustToWeight.ToString("F3")); hudString.Append(SimManager.LastStage.thrustToWeight.ToString("F3"));
   
if (this.CoMmarker.gameObject.activeInHierarchy && this.CoTmarker.gameObject.activeInHierarchy) if (this.CoMmarker.gameObject.activeInHierarchy && this.CoTmarker.gameObject.activeInHierarchy)
{ {
hudString.Append('\n'); hudString.Append('\n');
   
hudString.Append("Thrust Offset: "); hudString.Append("Thrust Offset: ");
hudString.Append( hudString.Append(
Vector3.Cross( Vector3.Cross(
this.CoTmarker.dirMarkerObject.transform.forward, this.CoTmarker.dirMarkerObject.transform.forward,
this.CoMmarker.posMarkerObject.transform.position - this.CoTmarker.posMarkerObject.transform.position this.CoMmarker.posMarkerObject.transform.position - this.CoTmarker.posMarkerObject.transform.position
).ToString("F3")); ).ToString("F3"));
} }
   
GUI.Label ( GUI.Label (
hudPos, hudPos,
hudString.ToString(), hudString.ToString(),
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 Engineer.VesselSimulator;
using KSP; using KSP;
using UnityEngine;  
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
  using System.Text;
  using ToadicusTools;
  using UnityEngine;
   
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;
   
protected List<Color> textColors = new List<Color>(); protected List<Color> textColors;
   
  protected Rect leftHUDdefaultPos;
  protected Rect rightHUDdefaultPos;
   
  [AVOID_SaveValue("leftHUDPos")]
  protected VOID_SaveValue<Rect> leftHUDPos;
  [AVOID_SaveValue("rightHUDPos")]
  protected VOID_SaveValue<Rect> rightHUDPos;
   
  [AVOID_SaveValue("positionsLocked")]
  protected VOID_SaveValue<bool> positionsLocked;
   
/* /*
* 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._colorIndex = 0;
   
  this.textColors = new List<Color>();
   
this.textColors.Add(Color.green); this.textColors.Add(Color.green);
this.textColors.Add(Color.black); this.textColors.Add(Color.black);
this.textColors.Add(Color.white); this.textColors.Add(Color.white);
this.textColors.Add(Color.red); this.textColors.Add(Color.red);
this.textColors.Add(Color.blue); this.textColors.Add(Color.blue);
this.textColors.Add(Color.yellow); this.textColors.Add(Color.yellow);
this.textColors.Add(Color.gray); this.textColors.Add(Color.gray);
this.textColors.Add(Color.cyan); this.textColors.Add(Color.cyan);
this.textColors.Add(Color.magenta); this.textColors.Add(Color.magenta);
   
VOID_Core.Instance.LabelStyles["hud"] = new GUIStyle(); this.leftHUDdefaultPos = new Rect(Screen.width * .375f - 300f, 0f, 300f, 90f);
VOID_Core.Instance.LabelStyles["hud"].normal.textColor = this.textColors [this.ColorIndex]; this.leftHUDPos = new Rect(this.leftHUDdefaultPos);
   
  this.rightHUDdefaultPos = new Rect(Screen.width * .625f, 0f, 300f, 90f);
  this.rightHUDPos = new Rect(this.rightHUDdefaultPos);
   
  this.positionsLocked = true;
   
Tools.PostDebugMessage ("VOID_HUD: Constructed."); Tools.PostDebugMessage ("VOID_HUD: Constructed.");
} }
   
  protected void leftHUDWindow(int id)
  {
  StringBuilder leftHUD;
   
  leftHUD = new StringBuilder();
   
  VOID_Core.Instance.LabelStyles["hud"].alignment = TextAnchor.UpperRight;
   
  if (VOID_Core.Instance.powerAvailable)
  {
  leftHUD.AppendFormat("Primary: {0} Inc: {1}",
  VOID_Data.primaryName.ValueUnitString(),
  VOID_Data.orbitInclination.ValueUnitString("F3")
  );
  leftHUD.AppendFormat("\nObt Alt: {0} Obt Vel: {1}",
  VOID_Data.orbitAltitude.ToSIString(),
  VOID_Data.orbitVelocity.ToSIString()
  );
  leftHUD.AppendFormat("\nAp: {0} ETA {1}",
  VOID_Data.orbitApoAlt.ToSIString(),
  VOID_Data.timeToApo.ValueUnitString()
  );
  leftHUD.AppendFormat("\nPe: {0} ETA {1}",
  VOID_Data.oribtPeriAlt.ToSIString(),
  VOID_Data.timeToPeri.ValueUnitString()
  );
  leftHUD.AppendFormat("\nTot Δv: {0} Stg Δv: {1}",
  VOID_Data.totalDeltaV.ToSIString(2),
  VOID_Data.stageDeltaV.ToSIString(2)
  );
  }
  else
  {
  VOID_Core.Instance.LabelStyles["hud"].normal.textColor = Color.red;
  leftHUD.Append(string.Intern("-- POWER LOST --"));
  }
   
  GUILayout.Label(leftHUD.ToString(), VOID_Core.Instance.LabelStyles["hud"], GUILayout.ExpandWidth(true));
   
  if (!this.positionsLocked)
  {
  GUI.DragWindow();
  }
   
  GUI.BringWindowToBack(id);
  }
   
  protected void rightHUDWindow(int id)
  {
  StringBuilder rightHUD;
   
  rightHUD = new StringBuilder();
   
  VOID_Core.Instance.LabelStyles["hud"].alignment = TextAnchor.UpperLeft;
   
  if (VOID_Core.Instance.powerAvailable)
  {
  rightHUD.AppendFormat("Biome: {0} Sit: {1}",
  VOID_Data.currBiome.ValueUnitString(),
  VOID_Data.expSituation.ValueUnitString()
  );
  rightHUD.AppendFormat("\nSrf Alt: {0} Srf Vel: {1}",
  VOID_Data.trueAltitude.ToSIString(),
  VOID_Data.surfVelocity.ToSIString()
  );
  rightHUD.AppendFormat("\nVer: {0} Hor: {1}",
  VOID_Data.vertVelocity.ToSIString(),
  VOID_Data.horzVelocity.ToSIString()
  );
  rightHUD.AppendFormat("\nLat: {0} Lon: {1}",
  VOID_Data.surfLatitude.ValueUnitString(),
  VOID_Data.surfLongitude.ValueUnitString()
  );
  rightHUD.AppendFormat("\nHdg: {0} Pit: {1}",
  VOID_Data.vesselHeading.ValueUnitString(),
  VOID_Data.vesselPitch.ToSIString(2)
  );
  }
  else
  {
  VOID_Core.Instance.LabelStyles["hud"].normal.textColor = Color.red;
  rightHUD.Append(string.Intern("-- POWER LOST --"));
  }
   
   
  GUILayout.Label(rightHUD.ToString(), VOID_Core.Instance.LabelStyles["hud"], GUILayout.ExpandWidth(true));
   
  if (!this.positionsLocked)
  {
  GUI.DragWindow();
  }
   
  GUI.BringWindowToBack(id);
  }
   
public override void DrawGUI() public override void DrawGUI()
{ {
GUI.skin = VOID_Core.Instance.Skin; if (!VOID_Core.Instance.LabelStyles.ContainsKey("hud"))
  {
if (VOID_Core.Instance.powerAvailable) VOID_Core.Instance.LabelStyles["hud"] = new GUIStyle(GUI.skin.label);
{ }
VOID_Core.Instance.LabelStyles["hud"].normal.textColor = textColors [ColorIndex];  
  VOID_Core.Instance.LabelStyles["hud"].normal.textColor = textColors [ColorIndex];
GUI.Label (  
new Rect ((Screen.width * .2083f), 0, 300f, 70f), if ((TimeWarp.WarpMode == TimeWarp.Modes.LOW) || (TimeWarp.CurrentRate <= TimeWarp.MaxPhysicsRate))
"Obt Alt: " + Tools.MuMech_ToSI (vessel.orbit.altitude) + "m" + {
" Obt Vel: " + Tools.MuMech_ToSI (vessel.orbit.vel.magnitude) + "m/s" + SimManager.RequestSimulation();
"\nAp: " + Tools.MuMech_ToSI (vessel.orbit.ApA) + "m" + }
" ETA " + Tools.ConvertInterval (vessel.orbit.timeToAp) +  
"\nPe: " + Tools.MuMech_ToSI (vessel.orbit.PeA) + "m" + this.leftHUDPos.value = GUI.Window(
" ETA " + Tools.ConvertInterval (vessel.orbit.timeToPe) + VOID_Core.Instance.windowID,
"\nInc: " + vessel.orbit.inclination.ToString ("F3") + "°" + this.leftHUDPos,
"\nPrimary: " + vessel.mainBody.bodyName, this.leftHUDWindow,
VOID_Core.Instance.LabelStyles["hud"]); GUIContent.none,
// Toadicus edit: Added "Biome: " line to surf/atmo HUD GUIStyle.none
GUI.Label ( );
new Rect ((Screen.width * .625f), 0, 300f, 90f),  
"Srf Alt: " + Tools.MuMech_ToSI (Tools.TrueAltitude (vessel)) + "m" + this.rightHUDPos.value = GUI.Window(
" Srf Vel: " + Tools.MuMech_ToSI (vessel.srf_velocity.magnitude) + "m/s" + VOID_Core.Instance.windowID,
"\nVer: " + Tools.MuMech_ToSI (vessel.verticalSpeed) + "m/s" + this.rightHUDPos,
" Hor: " + Tools.MuMech_ToSI (vessel.horizontalSrfSpeed) + "m/s" + this.rightHUDWindow,
"\nLat: " + Tools.GetLatitudeString (vessel, "F3") + GUIContent.none,
" Lon: " + Tools.GetLongitudeString (vessel, "F3") + GUIStyle.none
"\nHdg: " + Tools.MuMech_get_heading (vessel).ToString ("F2") + "° " + );
Tools.get_heading_text (Tools.MuMech_get_heading (vessel)) +  
"\nBiome: " + Tools.Toadicus_GetAtt (vessel).name +  
" Sit: " + vessel.GetExperimentSituation().HumanString(),  
VOID_Core.Instance.LabelStyles["hud"]);  
}  
else  
{  
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 * .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 (string.Intern("Change HUD color"), GUILayout.ExpandWidth (false)))
{ {
++this.ColorIndex; ++this.ColorIndex;
} }
   
  if (GUILayout.Button(string.Intern("Reset HUD Positions"), GUILayout.ExpandWidth(false)))
  {
  this.leftHUDPos = new Rect(this.leftHUDdefaultPos);
  this.rightHUDPos = new Rect(this.rightHUDdefaultPos);
  }
   
  this.positionsLocked = GUILayout.Toggle(this.positionsLocked,
  string.Intern("Lock HUD Positions"),
  GUILayout.ExpandWidth(false));
  }
  }
   
  public static partial class VOID_Data
  {
  public static readonly VOID_StrValue expSituation = new VOID_StrValue(
  "Situation",
  new Func<string> (() => VOID_Core.Instance.vessel.GetExperimentSituation().HumanString())
  );
   
  public static readonly VOID_DoubleValue vesselPitch = new VOID_DoubleValue(
  "Pitch",
  () => core.vessel.getSurfacePitch(),
  "°"
  );
   
  public static readonly VOID_DoubleValue stageMassFlow = new VOID_DoubleValue(
  "Stage Mass Flow",
  delegate()
  {
  if (SimManager.LastStage == null)
  {
  return double.NaN;
  }
   
  double stageIsp = SimManager.LastStage.isp;
  double stageThrust = SimManager.LastStage.actualThrust;
   
  return stageThrust / (stageIsp * KerbinGee);
  },
  "Mg/s"
  );
   
  public static readonly VOID_DoubleValue burnTimeCompleteAtNode = new VOID_DoubleValue(
  "Full burn time to complete at node",
  delegate()
  {
  if (SimManager.LastStage == null)
  {
  return double.NaN;
  }
   
  double nextManeuverDV = core.vessel.patchedConicSolver.maneuverNodes[0].DeltaV.magnitude;
  double stageThrust = SimManager.LastStage.actualThrust;
   
  return burnTime(nextManeuverDV, totalMass, stageMassFlow, stageThrust);
  },
  "s"
  );
   
  public static readonly VOID_DoubleValue burnTimeHalfDoneAtNode = new VOID_DoubleValue(
  "Full burn time to be half done at node",
  delegate()
  {
  if (SimManager.LastStage == null)
  {
  return double.NaN;
  }
   
  double nextManeuverDV = core.vessel.patchedConicSolver.maneuverNodes[0].DeltaV.magnitude / 2d;
  double stageThrust = SimManager.LastStage.actualThrust;
   
  return burnTime(nextManeuverDV, totalMass, stageMassFlow, stageThrust);
  },
  "s"
  );
   
  private static double burnTime(double deltaV, double initialMass, double massFlow, double thrust)
  {
  return initialMass / massFlow * (Math.Exp(deltaV * massFlow / thrust) - 1d);
} }
} }
} }
   
  //
  // VOID_Localization.cs
  //
  // Author:
  // toadicus <>
  //
  // Copyright (c) 2014 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/>.
 
  public static class VOID_Localization
  {
  public static string void_primary = "Primary";
  public static string void_altitude_asl = "Altitude (ASL)";
  public static string void_velocity = "Velocity";
  public static string void_apoapsis = "Apoapsis";
  public static string void_periapsis = "Periapsis";
  }
// //
// VOID_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;
  using ToadicusTools;
using UnityEngine; using UnityEngine;
   
namespace VOID namespace VOID
{ {
public abstract class VOID_Module : IVOID_Module public abstract class VOID_Module : IVOID_Module
{ {
/* /*
* Fields * Fields
* */ * */
[AVOID_SaveValue("Active")] [AVOID_SaveValue("Active")]
protected VOID_SaveValue<bool> _Active = false; protected VOID_SaveValue<bool> _Active = false;
protected bool _Running = false; protected bool _Running = false;
   
protected string _Name; protected string _Name;
   
protected float lastUpdate = 0; protected float lastUpdate = 0;
   
/* /*
* Properties * Properties
* */ * */
public virtual bool toggleActive public virtual bool toggleActive
{ {
get get
{ {
return this._Active; return this._Active;
} }
set set
{ {
this._Active.value = value; this._Active.value = 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 public virtual Vessel vessel
{ {
get get
{ {
return FlightGlobals.ActiveVessel; return FlightGlobals.ActiveVessel;
} }
} }
   
/* /*
* Methods * Methods
* */ * */
public void StartGUI() public void StartGUI()
{ {
if (!this.toggleActive || this.guiRunning) if (!this.toggleActive || this.guiRunning)
{ {
return; return;
} }
   
Tools.PostDebugMessage (string.Format("Adding {0} to the draw queue.", this.GetType().Name)); Tools.PostDebugMessage (string.Format("Adding {0} to the draw queue.", this.GetType().Name));
RenderingManager.AddToPostDrawQueue (3, this.DrawGUI); RenderingManager.AddToPostDrawQueue (3, this.DrawGUI);
this._Running = true; this._Running = true;
} }
   
public void StopGUI() public void StopGUI()
{ {
if (!this.guiRunning) if (!this.guiRunning)
{ {
return; return;
} }
Tools.PostDebugMessage (string.Format("Removing {0} from the draw queue.", this.GetType().Name)); Tools.PostDebugMessage (string.Format("Removing {0} from the draw queue.", this.GetType().Name));
RenderingManager.RemoveFromPostDrawQueue (3, this.DrawGUI); RenderingManager.RemoveFromPostDrawQueue (3, this.DrawGUI);
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 |
BindingFlags.FlattenHierarchy BindingFlags.FlattenHierarchy
)) ))
{ {
object[] attrs = field.GetCustomAttributes(typeof(AVOID_SaveValue), false); object[] attrs = field.GetCustomAttributes(typeof(AVOID_SaveValue), false);
   
if (attrs.Length == 0) { if (attrs.Length == 0) {
continue; continue;
} }
   
AVOID_SaveValue attr = attrs.FirstOrDefault () as AVOID_SaveValue; AVOID_SaveValue attr = attrs.FirstOrDefault () as AVOID_SaveValue;
   
string fieldName = string.Format("{0}_{1}", this.GetType().Name, attr.Name); string fieldName = string.Format("{0}_{1}", this.GetType().Name, attr.Name);
   
Tools.PostDebugMessage(string.Format("{0}: Loading field {1}.", this.GetType().Name, fieldName)); Tools.PostDebugMessage(string.Format("{0}: Loading field {1}.", this.GetType().Name, fieldName));
   
object fieldValue = 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 _SaveToConfig(KSP.IO.PluginConfiguration config) public virtual void _SaveToConfig(KSP.IO.PluginConfiguration config)
{ {
foreach (var field in this.GetType().GetFields( foreach (var field in this.GetType().GetFields(
BindingFlags.Instance | BindingFlags.Instance |
BindingFlags.NonPublic | BindingFlags.NonPublic |
BindingFlags.Public | BindingFlags.Public |
BindingFlags.FlattenHierarchy BindingFlags.FlattenHierarchy
)) ))
{ {
object[] attrs = field.GetCustomAttributes(typeof(AVOID_SaveValue), false); object[] attrs = field.GetCustomAttributes(typeof(AVOID_SaveValue), false);
   
if (attrs.Length == 0) { if (attrs.Length == 0) {
continue; continue;
} }
   
AVOID_SaveValue attr = attrs.FirstOrDefault () as AVOID_SaveValue; AVOID_SaveValue attr = attrs.FirstOrDefault () as AVOID_SaveValue;
   
string fieldName = string.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));
} }
} }
} }
   
public abstract class VOID_WindowModule : VOID_Module public abstract class VOID_WindowModule : VOID_Module
{ {
[AVOID_SaveValue("WindowPos")] [AVOID_SaveValue("WindowPos")]
protected Rect WindowPos = new Rect(Screen.width / 2, Screen.height / 2, 250f, 50f); protected Rect WindowPos = new Rect(Screen.width / 2, Screen.height / 2, 250f, 50f);
protected float defWidth = 250f; protected float defWidth = 250f;
protected float defHeight = 50f; protected float defHeight = 50f;
   
public virtual void ModuleWindow(int _) public virtual void ModuleWindow(int _)
{ {
if (VOID_Core.Instance.updateTimer - this.lastUpdate > VOID_Core.Instance.updatePeriod) { // if (VOID_Core.Instance.updateTimer - this.lastUpdate > VOID_Core.Instance.updatePeriod) {
foreach (var fieldinfo in this.GetType().GetFields( // foreach (var fieldinfo in this.GetType().GetFields(
BindingFlags.Instance | // BindingFlags.Instance |
BindingFlags.NonPublic | // BindingFlags.NonPublic |
BindingFlags.Public | // BindingFlags.Public |
BindingFlags.FlattenHierarchy // BindingFlags.FlattenHierarchy
)) // ))
{ // {
object field = null; // object field = null;
  //
try // try
{ // {
field = fieldinfo.GetValue (this); // field = fieldinfo.GetValue (this);
} // }
catch (NullReferenceException) { // catch (NullReferenceException) {
Tools.PostDebugMessage(string.Format( // Tools.PostDebugMessage(string.Format(
"{0}: caught NullReferenceException, could not get value for field {1}.", // "{0}: caught NullReferenceException, could not get value for field {1}.",
this.GetType().Name, // this.GetType().Name,
fieldinfo.Name // fieldinfo.Name
)); // ));
} // }
  //
if (field == null) { // if (field == null) {
continue; // continue;
} // }
  //
if (typeof(IVOID_DataValue).IsAssignableFrom (field.GetType ())) { // if (typeof(IVOID_DataValue).IsAssignableFrom (field.GetType ())) {
(field as IVOID_DataValue).Refresh (); // (field as IVOID_DataValue).Refresh ();
} // }
} // }
  //
this.lastUpdate = VOID_Core.Instance.updateTimer; // this.lastUpdate = VOID_Core.Instance.updateTimer;
} // }
} }
   
public override void DrawGUI() public override void DrawGUI()
{ {
GUI.skin = VOID_Core.Instance.Skin; GUI.skin = VOID_Core.Instance.Skin;
   
Rect _Pos = this.WindowPos; Rect _Pos = this.WindowPos;
   
_Pos = GUILayout.Window( _Pos = GUILayout.Window(
VOID_Core.Instance.windowID, VOID_Core.Instance.windowID,
_Pos, _Pos,
this.ModuleWindow, this.ModuleWindow,
this.Name, this.Name,
GUILayout.Width(this.defWidth), GUILayout.Width(this.defWidth),
GUILayout.Height(this.defHeight) GUILayout.Height(this.defHeight)
); );
   
_Pos = Tools.ClampRectToScreen (_Pos); _Pos = Tools.ClampRectToScreen (_Pos);
   
if (_Pos != this.WindowPos) if (_Pos != this.WindowPos)
{ {
this.WindowPos = _Pos; this.WindowPos = _Pos;
VOID_Core.Instance.configDirty = true; VOID_Core.Instance.configDirty = true;
} }
} }
} }
} }
   
   
// //
// 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 ToadicusTools;
using UnityEngine; using UnityEngine;
   
namespace VOID namespace VOID
{ {
public class VOID_Orbital : VOID_WindowModule public class VOID_Orbital : VOID_WindowModule
{ {
[AVOID_SaveValue("toggleExtended")] [AVOID_SaveValue("toggleExtended")]
protected VOID_SaveValue<bool> toggleExtended = false; protected VOID_SaveValue<bool> toggleExtended = false;
   
[AVOID_SaveValue("precisionValues")] [AVOID_SaveValue("precisionValues")]
protected long _precisionValues = 230584300921369395; protected long _precisionValues = 230584300921369395;
protected IntCollection precisionValues; protected IntCollection precisionValues;
   
protected VOID_StrValue primaryName = new VOID_StrValue ( public VOID_Orbital()
VOIDLabels.void_primary, {
  this._Name = "Orbital Information";
   
  this.WindowPos.x = Screen.width - 520f;
  this.WindowPos.y = 250f;
  }
   
  public override void ModuleWindow(int _)
  {
  base.ModuleWindow (_);
   
  int idx = 0;
   
  GUILayout.BeginVertical();
   
  VOID_Data.primaryName.DoGUIHorizontal ();
   
  this.precisionValues [idx]= (ushort)VOID_Data.orbitAltitude.DoGUIHorizontal (this.precisionValues [idx]);
  idx++;
   
  this.precisionValues [idx]= (ushort)VOID_Data.orbitVelocity.DoGUIHorizontal (this.precisionValues [idx]);
  idx++;
   
  this.precisionValues [idx]= (ushort)VOID_Data.orbitApoAlt.DoGUIHorizontal (this.precisionValues [idx]);
  idx++;
   
  VOID_Data.timeToApo.DoGUIHorizontal();
   
  this.precisionValues [idx]= (ushort)VOID_Data.oribtPeriAlt.DoGUIHorizontal (this.precisionValues [idx]);
  idx++;
   
  VOID_Data.timeToPeri.DoGUIHorizontal();
   
  VOID_Data.orbitInclination.DoGUIHorizontal("F3");
   
  this.precisionValues [idx]= (ushort)VOID_Data.gravityAccel.DoGUIHorizontal (this.precisionValues [idx]);
  idx++;
   
  this.toggleExtended.value = GUILayout.Toggle(this.toggleExtended, "Extended info");
   
  if (this.toggleExtended)
  {
  VOID_Data.orbitPeriod.DoGUIHorizontal();
   
  this.precisionValues [idx]= (ushort)VOID_Data.semiMajorAxis.DoGUIHorizontal (this.precisionValues [idx]);
  idx++;
   
  VOID_Data.eccentricity.DoGUIHorizontal("F4");
   
  VOID_Data.meanAnomaly.DoGUIHorizontal("F3");
   
  VOID_Data.trueAnomaly.DoGUIHorizontal("F3");
   
  VOID_Data.eccAnomaly.DoGUIHorizontal("F3");
   
  VOID_Data.longitudeAscNode.DoGUIHorizontal("F3");
   
  VOID_Data.argumentPeriapsis.DoGUIHorizontal("F3");
   
  VOID_Data.localSiderealLongitude.DoGUIHorizontal("F3");
  }
   
  GUILayout.EndVertical();
  GUI.DragWindow();
  }
   
  public override void LoadConfig ()
  {
  base.LoadConfig ();
   
  this.precisionValues = new IntCollection (4, this._precisionValues);
  }
   
  public override void _SaveToConfig (KSP.IO.PluginConfiguration config)
  {
  this._precisionValues = this.precisionValues.collection;
   
  base._SaveToConfig (config);
  }
  }
   
   
  public static partial class VOID_Data
  {
  public static readonly VOID_StrValue primaryName = new VOID_StrValue (
  VOID_Localization.void_primary,
new Func<string> (() => VOID_Core.Instance.vessel.mainBody.name) new Func<string> (() => VOID_Core.Instance.vessel.mainBody.name)
); );
   
protected VOID_DoubleValue orbitAltitude = new VOID_DoubleValue ( public static readonly VOID_DoubleValue orbitAltitude = new VOID_DoubleValue (
"Altitude (ASL)", "Altitude (ASL)",
new Func<double> (() => VOID_Core.Instance.vessel.orbit.altitude), new Func<double> (() => VOID_Core.Instance.vessel.orbit.altitude),
"m" "m"
); );
   
protected VOID_DoubleValue orbitVelocity = new VOID_DoubleValue ( public static readonly VOID_DoubleValue orbitVelocity = new VOID_DoubleValue (
VOIDLabels.void_velocity, VOID_Localization.void_velocity,
new Func<double> (() => VOID_Core.Instance.vessel.orbit.vel.magnitude), new Func<double> (() => VOID_Core.Instance.vessel.orbit.vel.magnitude),
"m/s" "m/s"
); );
   
protected VOID_DoubleValue orbitApoAlt = new VOID_DoubleValue( public static readonly VOID_DoubleValue orbitApoAlt = new VOID_DoubleValue(
VOIDLabels.void_apoapsis, VOID_Localization.void_apoapsis,
new Func<double>(() => VOID_Core.Instance.vessel.orbit.ApA), new Func<double>(() => VOID_Core.Instance.vessel.orbit.ApA),
"m" "m"
); );
   
protected VOID_DoubleValue oribtPeriAlt = new VOID_DoubleValue( public static readonly VOID_DoubleValue oribtPeriAlt = new VOID_DoubleValue(
VOIDLabels.void_periapsis, VOID_Localization.void_periapsis,
new Func<double>(() => VOID_Core.Instance.vessel.orbit.PeA), new Func<double>(() => VOID_Core.Instance.vessel.orbit.PeA),
"m" "m"
); );
   
protected VOID_StrValue timeToApo = new VOID_StrValue( public static readonly VOID_StrValue timeToApo = new VOID_StrValue(
"Time to Apoapsis", "Time to Apoapsis",
new Func<string>(() => Tools.ConvertInterval(VOID_Core.Instance.vessel.orbit.timeToAp)) new Func<string>(() => Tools.ConvertInterval(VOID_Core.Instance.vessel.orbit.timeToAp))
); );
   
protected VOID_StrValue timeToPeri = new VOID_StrValue( public static readonly VOID_StrValue timeToPeri = new VOID_StrValue(
"Time to Periapsis", "Time to Periapsis",
new Func<string>(() => Tools.ConvertInterval(VOID_Core.Instance.vessel.orbit.timeToPe)) new Func<string>(() => Tools.ConvertInterval(VOID_Core.Instance.vessel.orbit.timeToPe))
); );
   
protected VOID_DoubleValue orbitInclination = new VOID_DoubleValue( public static readonly VOID_DoubleValue orbitInclination = new VOID_DoubleValue(
"Inclination", "Inclination",
new Func<double>(() => VOID_Core.Instance.vessel.orbit.inclination), new Func<double>(() => VOID_Core.Instance.vessel.orbit.inclination),
"°" "°"
); );
   
protected VOID_DoubleValue gravityAccel = new VOID_DoubleValue( public static readonly VOID_DoubleValue gravityAccel = new VOID_DoubleValue(
"Gravity", "Gravity",
delegate() delegate()
{ {
double orbitRadius = VOID_Core.Instance.vessel.mainBody.Radius + double orbitRadius = VOID_Core.Instance.vessel.mainBody.Radius +
VOID_Core.Instance.vessel.mainBody.GetAltitude(VOID_Core.Instance.vessel.findWorldCenterOfMass()); VOID_Core.Instance.vessel.mainBody.GetAltitude(VOID_Core.Instance.vessel.findWorldCenterOfMass());
return (VOID_Core.Constant_G * VOID_Core.Instance.vessel.mainBody.Mass) / return (VOID_Core.Constant_G * VOID_Core.Instance.vessel.mainBody.Mass) /
Math.Pow(orbitRadius, 2); Math.Pow(orbitRadius, 2);
}, },
"m/s²" "m/s²"
); );
   
protected VOID_StrValue orbitPeriod = new VOID_StrValue( public static readonly VOID_StrValue orbitPeriod = new VOID_StrValue(
"Period", "Period",
new Func<string>(() => Tools.ConvertInterval(VOID_Core.Instance.vessel.orbit.period)) new Func<string>(() => Tools.ConvertInterval(VOID_Core.Instance.vessel.orbit.period))
); );
   
protected VOID_DoubleValue semiMajorAxis = new VOID_DoubleValue( public static readonly VOID_DoubleValue semiMajorAxis = new VOID_DoubleValue(
"Semi-Major Axis", "Semi-Major Axis",
new Func<double>(() => VOID_Core.Instance.vessel.orbit.semiMajorAxis), new Func<double>(() => VOID_Core.Instance.vessel.orbit.semiMajorAxis),
"m" "m"
); );
   
protected VOID_DoubleValue eccentricity = new VOID_DoubleValue( public static readonly VOID_DoubleValue eccentricity = new VOID_DoubleValue(
"Eccentricity", "Eccentricity",
new Func<double>(() => VOID_Core.Instance.vessel.orbit.eccentricity), new Func<double>(() => VOID_Core.Instance.vessel.orbit.eccentricity),
"" ""
); );
   
protected VOID_DoubleValue meanAnomaly = new VOID_DoubleValue( public static readonly VOID_DoubleValue meanAnomaly = new VOID_DoubleValue(
"Mean Anomaly", "Mean Anomaly",
new Func<double>(() => VOID_Core.Instance.vessel.orbit.meanAnomaly * 180d / Math.PI), new Func<double>(() => VOID_Core.Instance.vessel.orbit.meanAnomaly * 180d / Math.PI),
"°" "°"
); );
   
protected VOID_DoubleValue trueAnomaly = new VOID_DoubleValue( public static readonly VOID_DoubleValue trueAnomaly = new VOID_DoubleValue(
"True Anomaly", "True Anomaly",
new Func<double>(() => VOID_Core.Instance.vessel.orbit.trueAnomaly), new Func<double>(() => VOID_Core.Instance.vessel.orbit.trueAnomaly),
"°" "°"
); );
   
protected VOID_DoubleValue eccAnomaly = new VOID_DoubleValue( public static readonly VOID_DoubleValue eccAnomaly = new VOID_DoubleValue(
"Eccentric Anomaly", "Eccentric Anomaly",
new Func<double>(() => VOID_Core.Instance.vessel.orbit.eccentricAnomaly * 180d / Math.PI), new Func<double>(() => VOID_Core.Instance.vessel.orbit.eccentricAnomaly * 180d / Math.PI),
"°" "°"
); );
   
protected VOID_DoubleValue longitudeAscNode = new VOID_DoubleValue( public static readonly VOID_DoubleValue longitudeAscNode = new VOID_DoubleValue(
"Long. Ascending Node", "Long. Ascending Node",
new Func<double>(() => VOID_Core.Instance.vessel.orbit.LAN), new Func<double>(() => VOID_Core.Instance.vessel.orbit.LAN),
"°" "°"
); );
   
protected VOID_DoubleValue argumentPeriapsis = new VOID_DoubleValue( public static readonly VOID_DoubleValue argumentPeriapsis = new VOID_DoubleValue(
"Argument of Periapsis", "Argument of Periapsis",
new Func<double>(() => VOID_Core.Instance.vessel.orbit.argumentOfPeriapsis), new Func<double>(() => VOID_Core.Instance.vessel.orbit.argumentOfPeriapsis),
"°" "°"
); );
   
protected VOID_DoubleValue localSiderealLongitude = new VOID_DoubleValue( public static readonly VOID_DoubleValue localSiderealLongitude = new VOID_DoubleValue(
"Local Sidereal Longitude", "Local Sidereal Longitude",
new Func<double>(() => Tools.FixDegreeDomain( new Func<double>(() => Tools.FixDegreeDomain(
VOID_Core.Instance.vessel.longitude + VOID_Core.Instance.vessel.orbit.referenceBody.rotationAngle)), VOID_Core.Instance.vessel.longitude + VOID_Core.Instance.vessel.orbit.referenceBody.rotationAngle)),
"°" "°"
); );
   
public VOID_Orbital()  
{  
this._Name = "Orbital Information";  
   
this.WindowPos.x = Screen.width - 520f;  
this.WindowPos.y = 250f;  
}  
   
public override void ModuleWindow(int _)  
{  
base.ModuleWindow (_);  
   
int idx = 0;  
   
GUILayout.BeginVertical();  
   
this.primaryName.DoGUIHorizontal ();  
   
this.precisionValues [idx]= (ushort)this.orbitAltitude.DoGUIHorizontal (this.precisionValues [idx]);  
idx++;  
   
this.precisionValues [idx]= (ushort)this.orbitVelocity.DoGUIHorizontal (this.precisionValues [idx]);  
idx++;  
   
this.precisionValues [idx]= (ushort)this.orbitApoAlt.DoGUIHorizontal (this.precisionValues [idx]);  
idx++;  
   
this.timeToApo.DoGUIHorizontal();  
   
this.precisionValues [idx]= (ushort)this.oribtPeriAlt.DoGUIHorizontal (this.precisionValues [idx]);  
idx++;  
   
this.timeToPeri.DoGUIHorizontal();  
   
this.orbitInclination.DoGUIHorizontal("F3");  
   
this.precisionValues [idx]= (ushort)this.gravityAccel.DoGUIHorizontal (this.precisionValues [idx]);  
idx++;  
   
this.toggleExtended.value = GUILayout.Toggle(this.toggleExtended, "Extended info");  
   
if (this.toggleExtended)  
{  
this.orbitPeriod.DoGUIHorizontal();  
   
this.precisionValues [idx]= (ushort)this.semiMajorAxis.DoGUIHorizontal (this.precisionValues [idx]);  
idx++;  
   
this.eccentricity.DoGUIHorizontal("F4");  
   
this.meanAnomaly.DoGUIHorizontal("F3");  
   
this.trueAnomaly.DoGUIHorizontal("F3");  
   
this.eccAnomaly.DoGUIHorizontal("F3");  
   
this.longitudeAscNode.DoGUIHorizontal("F3");  
   
this.argumentPeriapsis.DoGUIHorizontal("F3");  
   
this.localSiderealLongitude.DoGUIHorizontal("F3");  
}  
   
GUILayout.EndVertical();  
GUI.DragWindow();  
}  
   
public override void LoadConfig ()  
{  
base.LoadConfig ();  
   
this.precisionValues = new IntCollection (4, this._precisionValues);  
}  
   
public override void _SaveToConfig (KSP.IO.PluginConfiguration config)  
{  
this._precisionValues = this.precisionValues.collection;  
   
base._SaveToConfig (config);  
}  
} }
} }
   
   
// //
// 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 ToadicusTools;
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 == 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 == 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 = v.longitude + v.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_Config.cs // VOID_Config.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.Collections.Generic; using System.Collections.Generic;
using KSP; using ToadicusTools;
using UnityEngine; using UnityEngine;
   
namespace VOID namespace VOID
{ {
public struct VOID_SaveValue<T> : IVOID_SaveValue public struct VOID_SaveValue<T> : IVOID_SaveValue
{ {
private T _value; private T _value;
private Type _type; private Type _type;
   
private VOID_Core Core private VOID_Core Core
{ {
get get
{ {
if (HighLogic.LoadedSceneIsEditor) if (HighLogic.LoadedSceneIsEditor)
{ {
if (VOID_EditorCore.Initialized) if (VOID_EditorCore.Initialized)
{ {
return VOID_EditorCore.Instance; return VOID_EditorCore.Instance;
} }
} }
else if (HighLogic.LoadedSceneIsFlight) else if (HighLogic.LoadedSceneIsFlight)
{ {
if (VOID_Core.Initialized) if (VOID_Core.Initialized)
{ {
return VOID_Core.Instance; return VOID_Core.Instance;
} }
} }
return null; return null;
} }
} }
   
public T value public T value
{ {
get get
{ {
return this._value; return this._value;
} }
set set
{ {
if (this.Core != null && !System.Object.Equals(this._value, value)) if (this.Core != null && !System.Object.Equals(this._value, value))
{ {
Tools.PostDebugMessage (string.Format ( Tools.PostDebugMessage (string.Format (
"VOID: Dirtying config for type {0} in method {1}." + "VOID: Dirtying config for type {0} in method {1}." +
"\n\t Old Value: {2}, New Value: {3}" + "\n\t Old Value: {2}, New Value: {3}" +
"\n\t Object.Equals(New, Old): {4}", "\n\t Object.Equals(New, Old): {4}",
this._type, this._type,
new System.Diagnostics.StackTrace().GetFrame(1).GetMethod(), new System.Diagnostics.StackTrace().GetFrame(1).GetMethod(),
this._value, this._value,
value, value,
System.Object.Equals(this._value, value) System.Object.Equals(this._value, value)
)); ));
this.Core.configDirty = true; this.Core.configDirty = true;
} }
this._value = value; this._value = value;
} }
} }
   
public Type type public Type type
{ {
get get
{ {
if (this._type == null && this._value != null) if (this._type == null && this._value != null)
{ {
this._type = this._value.GetType (); this._type = this._value.GetType ();
} }
return this._type; return this._type;
} }
set set
{ {
this._type = value; this._type = value;
} }
} }
   
public object AsType public object AsType
{ {
get get
{ {
return (T)this._value; return (T)this._value;
} }
} }
   
public void SetValue(object v) public void SetValue(object v)
{ {
this.value = (T)v; this.value = (T)v;
} }
   
public static implicit operator T(VOID_SaveValue<T> v) public static implicit operator T(VOID_SaveValue<T> v)
{ {
return (T)v.value; return (T)v.value;
} }
   
public static implicit operator VOID_SaveValue<T>(T v) public static implicit operator VOID_SaveValue<T>(T v)
{ {
VOID_SaveValue<T> r = new VOID_SaveValue<T>(); VOID_SaveValue<T> r = new VOID_SaveValue<T>();
r.type = v.GetType(); r.type = v.GetType();
r.value = v; r.value = v;
   
return r; return r;
} }
   
public override string ToString() public override string ToString()
{ {
return this.value.ToString(); return this.value.ToString();
} }
} }
   
public interface IVOID_SaveValue public interface IVOID_SaveValue
{ {
Type type { get; } Type type { get; }
object AsType { get; } object AsType { get; }
void SetValue(object v); void SetValue(object v);
} }
   
[AttributeUsage(AttributeTargets.Field)] [AttributeUsage(AttributeTargets.Field)]
public class AVOID_SaveValue : Attribute public class AVOID_SaveValue : Attribute
{ {
protected string _name; protected string _name;
   
public string Name public string Name
{ {
get get
{ {
return this._name; return this._name;
} }
} }
   
public AVOID_SaveValue(string fieldName) public AVOID_SaveValue(string fieldName)
{ {
this._name = fieldName; this._name = fieldName;
} }
} }
} }
   
   
// //
// 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 ToadicusTools;
using UnityEngine; using UnityEngine;
   
namespace VOID namespace VOID
{ {
public class VOID_SurfAtmo : VOID_WindowModule public class VOID_SurfAtmo : VOID_WindowModule
{ {
[AVOID_SaveValue("precisionValues")] [AVOID_SaveValue("precisionValues")]
protected long _precisionValues = 230584300921369395; protected long _precisionValues = 230584300921369395;
protected IntCollection precisionValues; protected IntCollection precisionValues;
   
protected VOID_DoubleValue trueAltitude = new VOID_DoubleValue(  
"Altitude (true)",  
delegate()  
{  
double alt_true = VOID_Core.Instance.vessel.orbit.altitude - VOID_Core.Instance.vessel.terrainAltitude;  
// HACK: This assumes that on worlds with oceans, all water is fixed at 0 m,  
// and water covers the whole surface at 0 m.  
if (VOID_Core.Instance.vessel.terrainAltitude < 0 && VOID_Core.Instance.vessel.mainBody.ocean )  
alt_true = VOID_Core.Instance.vessel.orbit.altitude;  
return alt_true;  
},  
"m"  
);  
   
protected VOID_StrValue surfLatitude = new VOID_StrValue(  
"Latitude",  
new Func<string> (() => Tools.GetLatitudeString(VOID_Core.Instance.vessel))  
);  
   
protected VOID_StrValue surfLongitude = new VOID_StrValue(  
"Longitude",  
new Func<string> (() => Tools.GetLongitudeString(VOID_Core.Instance.vessel))  
);  
   
protected VOID_StrValue vesselHeading = new VOID_StrValue(  
"Heading",  
delegate()  
{  
double heading = Tools.MuMech_get_heading(VOID_Core.Instance.vessel);  
string cardinal = Tools.get_heading_text(heading);  
   
return string.Format(  
"{0}° {1}",  
heading.ToString("F2"),  
cardinal  
);  
}  
);  
   
protected VOID_DoubleValue terrainElevation = new VOID_DoubleValue(  
"Terrain elevation",  
new Func<double> (() => VOID_Core.Instance.vessel.terrainAltitude),  
"m"  
);  
   
protected VOID_DoubleValue surfVelocity = new VOID_DoubleValue(  
"Surface velocity",  
new Func<double> (() => VOID_Core.Instance.vessel.srf_velocity.magnitude),  
"m/s"  
);  
   
protected VOID_DoubleValue vertVelocity = new VOID_DoubleValue(  
"Vertical speed",  
new Func<double> (() => VOID_Core.Instance.vessel.verticalSpeed),  
"m/s"  
);  
   
protected VOID_DoubleValue horzVelocity = new VOID_DoubleValue(  
"Horizontal speed",  
new Func<double> (() => VOID_Core.Instance.vessel.horizontalSrfSpeed),  
"m/s"  
);  
   
protected VOID_FloatValue temperature = new VOID_FloatValue(  
"Temperature",  
new Func<float> (() => VOID_Core.Instance.vessel.flightIntegrator.getExternalTemperature()),  
"°C"  
);  
   
protected VOID_DoubleValue atmDensity = new VOID_DoubleValue (  
"Atmosphere Density",  
new Func<double> (() => VOID_Core.Instance.vessel.atmDensity * 1000f),  
"g/m³"  
);  
   
protected VOID_DoubleValue atmPressure = new VOID_DoubleValue (  
"Pressure",  
new Func<double> (() => VOID_Core.Instance.vessel.staticPressure),  
"atm"  
);  
   
protected VOID_FloatValue atmLimit = new VOID_FloatValue(  
"Atmosphere Limit",  
new Func<float> (() => VOID_Core.Instance.vessel.mainBody.maxAtmosphereAltitude),  
"m"  
);  
   
protected VOID_StrValue currBiome = new VOID_StrValue(  
"Biome",  
new Func<string> (() => Tools.Toadicus_GetAtt(VOID_Core.Instance.vessel).name)  
);  
   
public VOID_SurfAtmo() public VOID_SurfAtmo()
{ {
this._Name = "Surface & Atmospheric Information"; this._Name = "Surface & Atmospheric Information";
   
this.WindowPos.x = Screen.width - 260f; this.WindowPos.x = Screen.width - 260f;
this.WindowPos.y = 85; this.WindowPos.y = 85;
} }
   
public override void ModuleWindow(int _) public override void ModuleWindow(int _)
{ {
base.ModuleWindow (_); base.ModuleWindow (_);
   
int idx = 0; int idx = 0;
   
GUILayout.BeginVertical(); GUILayout.BeginVertical();
   
this.precisionValues [idx]= (ushort)this.trueAltitude.DoGUIHorizontal (this.precisionValues [idx]); this.precisionValues [idx]= (ushort)VOID_Data.trueAltitude.DoGUIHorizontal (this.precisionValues [idx]);
idx++; idx++;
   
this.surfLatitude.DoGUIHorizontal (); VOID_Data.surfLatitude.DoGUIHorizontal ();
   
this.surfLongitude.DoGUIHorizontal (); VOID_Data.surfLongitude.DoGUIHorizontal ();
   
this.vesselHeading.DoGUIHorizontal (); VOID_Data.vesselHeading.DoGUIHorizontal ();
   
this.precisionValues [idx]= (ushort)this.terrainElevation.DoGUIHorizontal (this.precisionValues [idx]); this.precisionValues [idx]= (ushort)VOID_Data.terrainElevation.DoGUIHorizontal (this.precisionValues [idx]);
idx++; idx++;
   
this.precisionValues [idx]= (ushort)this.surfVelocity.DoGUIHorizontal (this.precisionValues [idx]); this.precisionValues [idx]= (ushort)VOID_Data.surfVelocity.DoGUIHorizontal (this.precisionValues [idx]);
idx++; idx++;
   
this.precisionValues [idx]= (ushort)this.vertVelocity.DoGUIHorizontal (this.precisionValues [idx]); this.precisionValues [idx]= (ushort)VOID_Data.vertVelocity.DoGUIHorizontal (this.precisionValues [idx]);
idx++; idx++;
   
this.precisionValues [idx]= (ushort)this.horzVelocity.DoGUIHorizontal (this.precisionValues [idx]); this.precisionValues [idx]= (ushort)VOID_Data.horzVelocity.DoGUIHorizontal (this.precisionValues [idx]);
idx++; idx++;
   
this.temperature.DoGUIHorizontal ("F2"); VOID_Data.temperature.DoGUIHorizontal ("F2");
   
this.atmDensity.DoGUIHorizontal (3); VOID_Data.atmDensity.DoGUIHorizontal (3);
   
this.atmPressure.DoGUIHorizontal ("F2"); VOID_Data.atmPressure.DoGUIHorizontal ("F2");
   
this.precisionValues [idx]= (ushort)this.atmLimit.DoGUIHorizontal (this.precisionValues [idx]); this.precisionValues [idx]= (ushort)VOID_Data.atmLimit.DoGUIHorizontal (this.precisionValues [idx]);
idx++; idx++;
   
// Toadicus edit: added Biome // Toadicus edit: added Biome
this.currBiome.DoGUIHorizontal (); VOID_Data.currBiome.DoGUIHorizontal ();
   
GUILayout.EndVertical(); GUILayout.EndVertical();
GUI.DragWindow(); GUI.DragWindow();
} }
   
public override void LoadConfig () public override void LoadConfig ()
{ {
base.LoadConfig (); base.LoadConfig ();
   
this.precisionValues = new IntCollection (4, this._precisionValues); this.precisionValues = new IntCollection (4, this._precisionValues);
} }
   
public override void _SaveToConfig (KSP.IO.PluginConfiguration config) public override void _SaveToConfig (KSP.IO.PluginConfiguration config)
{ {
this._precisionValues = this.precisionValues.collection; this._precisionValues = this.precisionValues.collection;
   
base._SaveToConfig (config); base._SaveToConfig (config);
} }
} }
   
  public static partial class VOID_Data
  {
  public static readonly VOID_DoubleValue trueAltitude = new VOID_DoubleValue(
  "Altitude (true)",
  delegate()
  {
  double alt_true = VOID_Core.Instance.vessel.orbit.altitude - VOID_Core.Instance.vessel.terrainAltitude;
  // HACK: This assumes that on worlds with oceans, all water is fixed at 0 m,
  // and water covers the whole surface at 0 m.
  if (VOID_Core.Instance.vessel.terrainAltitude < 0 && VOID_Core.Instance.vessel.mainBody.ocean )
  alt_true = VOID_Core.Instance.vessel.orbit.altitude;
  return alt_true;
  },
  "m"
  );
   
  public static readonly VOID_StrValue surfLatitude = new VOID_StrValue(
  "Latitude",
  new Func<string> (() => Tools.GetLatitudeString(VOID_Core.Instance.vessel))
  );
   
  public static readonly VOID_StrValue surfLongitude = new VOID_StrValue(
  "Longitude",
  new Func<string> (() => Tools.GetLongitudeString(VOID_Core.Instance.vessel))
  );
   
  public static readonly VOID_StrValue vesselHeading = new VOID_StrValue(
  "Heading",
  delegate()
  {
  double heading = core.vessel.getSurfaceHeading();
  string cardinal = Tools.get_heading_text(heading);
   
  return string.Format(
  "{0}° {1}",
  heading.ToString("F2"),
  cardinal
  );
  }
  );
   
  public static readonly VOID_DoubleValue terrainElevation = new VOID_DoubleValue(
  "Terrain elevation",
  new Func<double> (() => VOID_Core.Instance.vessel.terrainAltitude),
  "m"
  );
   
  public static readonly VOID_DoubleValue surfVelocity = new VOID_DoubleValue(
  "Surface velocity",
  new Func<double> (() => VOID_Core.Instance.vessel.srf_velocity.magnitude),
  "m/s"
  );
   
  public static readonly VOID_DoubleValue vertVelocity = new VOID_DoubleValue(
  "Vertical speed",
  new Func<double> (() => VOID_Core.Instance.vessel.verticalSpeed),
  "m/s"
  );
   
  public static readonly VOID_DoubleValue horzVelocity = new VOID_DoubleValue(
  "Horizontal speed",
  new Func<double> (() => VOID_Core.Instance.vessel.horizontalSrfSpeed),
  "m/s"
  );
   
  public static readonly VOID_FloatValue temperature = new VOID_FloatValue(
  "Temperature",
  new Func<float> (() => VOID_Core.Instance.vessel.flightIntegrator.getExternalTemperature()),
  "°C"
  );
   
  public static readonly VOID_DoubleValue atmDensity = new VOID_DoubleValue (
  "Atmosphere Density",
  new Func<double> (() => VOID_Core.Instance.vessel.atmDensity * 1000f),
  "g/m³"
  );
   
  public static readonly VOID_DoubleValue atmPressure = new VOID_DoubleValue (
  "Pressure",
  new Func<double> (() => VOID_Core.Instance.vessel.staticPressure),
  "atm"
  );
   
  public static readonly VOID_FloatValue atmLimit = new VOID_FloatValue(
  "Atmosphere Limit",
  new Func<float> (() => VOID_Core.Instance.vessel.mainBody.maxAtmosphereAltitude),
  "m"
  );
   
  public static readonly VOID_StrValue currBiome = new VOID_StrValue(
  "Biome",
  new Func<string> (() => Tools.GetBiome(VOID_Core.Instance.vessel).name)
  );
   
  }
} }
file:b/VOID_Tools.cs (new)
  //
  // VOID_Tools.cs
  //
  // Author:
  // toadicus <>
  //
  // Copyright (c) 2014 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 ToadicusTools
  {
  public static partial class Tools
  {
  #region VESSEL_EXTENSIONS_SCIENCE
  public static CBAttributeMap.MapAttribute GetBiome(this Vessel vessel)
  {
  CBAttributeMap.MapAttribute mapAttribute;
 
  try
  {
  CBAttributeMap BiomeMap = vessel.mainBody.BiomeMap;
 
  double lat = vessel.latitude * Math.PI / 180d;
  double lon = vessel.longitude * Math.PI / 180d;
 
  mapAttribute = BiomeMap.GetAtt(lat, lon);
 
  /*
  lon -= Math.PI / 2d;
 
  if (lon < 0d)
  {
  lon += 2d * Math.PI;
  }
 
  float v = (float)(lat / Math.PI) + 0.5f;
  float u = (float)(lon / (2d * Math.PI));
 
  Color pixelBilinear = BiomeMap.Map.GetPixelBilinear(u, v);
  mapAttribute = BiomeMap.defaultAttribute;
 
  if (BiomeMap.Map != null)
  {
  if (BiomeMap.exactSearch)
  {
  for (int i = 0; i < BiomeMap.Attributes.Length; ++i)
  {
  if (pixelBilinear == BiomeMap.Attributes[i].mapColor)
  {
  mapAttribute = BiomeMap.Attributes[i];
  }
  }
  }
  else
  {
  float zero = 0;
  float num = 1 / zero;
  for (int j = 0; j < BiomeMap.Attributes.Length; ++j)
  {
  Color mapColor = BiomeMap.Attributes[j].mapColor;
  float sqrMagnitude = ((Vector4)(mapColor - pixelBilinear)).sqrMagnitude;
  if (sqrMagnitude < num)
  {
  bool testCase = true;
  if (BiomeMap.nonExactThreshold != -1)
  {
  testCase = (sqrMagnitude < BiomeMap.nonExactThreshold);
  }
  if (testCase)
  {
  mapAttribute = BiomeMap.Attributes[j];
  num = sqrMagnitude;
  }
  }
  }
  }
  }
  */
  }
  catch (NullReferenceException)
  {
  mapAttribute = new CBAttributeMap.MapAttribute();
  mapAttribute.name = "N/A";
  }
 
  return mapAttribute;
  }
 
  public static 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";
  }
  }
  #endregion
 
  #region VESSEL_EXTENSIONS_LAT_LONG
  public static string GetLongitudeString(this Vessel vessel, string format = "F4")
  {
  string dir_long = "W";
  double v_long = vessel.longitude;
 
  v_long = FixDegreeDomain(v_long);
 
  if (v_long < -180d)
  {
  v_long += 360d;
  }
  if (v_long >= 180)
  {
  v_long -= 360d;
  }
 
  if (v_long > 0)
  dir_long = "E";
 
  return string.Format("{0}° {1}", Math.Abs(v_long).ToString(format), dir_long);
  }
 
  public static string GetLatitudeString(this Vessel vessel, string format = "F4")
  {
  string dir_lat = "S";
  double v_lat = vessel.latitude;
  if (v_lat > 0)
  dir_lat = "N";
 
  return string.Format("{0}° {1}", Math.Abs(v_lat).ToString(format), dir_lat);
  }
  #endregion
 
  #region VESSEL_EXTENSIONS_GENERAL
  public static double TrueAltitude(Vessel vessel)
  {
  double trueAltitude = vessel.orbit.altitude - vessel.terrainAltitude;
 
  // HACK: This assumes that on worlds with oceans, all water is fixed at 0 m,
  // and water covers the whole surface at 0 m.
  if (vessel.terrainAltitude < 0 && vessel.mainBody.ocean)
  {
  trueAltitude = vessel.orbit.altitude;
  }
 
  return trueAltitude;
  }
 
  public static double Radius(this Vessel vessel)
  {
  double radius;
 
  radius = vessel.altitude;
 
  if (vessel.mainBody != null)
  {
  radius += vessel.mainBody.Radius;
  }
 
  return radius;
  }
  #endregion
 
  #region GEOMETRY_UTILS
  public static double FixAngleDomain(double Angle, bool Degrees = false)
  {
  double Extent = 2d * Math.PI;
  if (Degrees)
  {
  Extent = 360d;
  }
 
  Angle = Angle % (Extent);
  if (Angle < 0d)
  {
  Angle += Extent;
  }
 
  return Angle;
  }
 
  public static double FixDegreeDomain(double Angle)
  {
  return FixAngleDomain(Angle, true);
  }
  #endregion
 
  public static string ConvertInterval(double seconds)
  {
  string format_1 = "{0:D1}y {1:D1}d {2:D2}h {3:D2}m {4:D2}.{5:D1}s";
  string format_2 = "{0:D1}d {1:D2}h {2:D2}m {3:D2}.{4:D1}s";
  string format_3 = "{0:D2}h {1:D2}m {2:D2}.{3:D1}s";
 
  TimeSpan interval;
 
  try
  {
  interval = TimeSpan.FromSeconds(seconds);
  }
  catch (OverflowException)
  {
  return "NaN";
  }
 
  int years = interval.Days / 365;
 
  string output;
  if (years > 0)
  {
  output = string.Format(format_1,
  years,
  interval.Days - (years * 365), // subtract years * 365 for accurate day count
  interval.Hours,
  interval.Minutes,
  interval.Seconds,
  interval.Milliseconds.ToString().Substring(0, 1));
  }
  else if (interval.Days > 0)
  {
  output = string.Format(format_2,
  interval.Days,
  interval.Hours,
  interval.Minutes,
  interval.Seconds,
  interval.Milliseconds.ToString().Substring(0, 1));
  }
  else
  {
  output = string.Format(format_3,
  interval.Hours,
  interval.Minutes,
  interval.Seconds,
  interval.Milliseconds.ToString().Substring(0, 1));
  }
  return output;
  }
 
  public static string UppercaseFirst(string s)
  {
  if (string.IsNullOrEmpty(s))
  {
  return string.Empty;
  }
  char[] a = s.ToCharArray();
  a[0] = char.ToUpper(a[0]);
  return new string(a);
  }
 
  //transfer angles
  public static double Nivvy_CalcTransferPhaseAngle(double r_current, double r_target, double grav_param)
  {
  double T_target = (2 * Math.PI) * Math.Sqrt(Math.Pow((r_target / 1000), 3) / (grav_param / 1000000000));
  double T_transfer = (2 * Math.PI) * Math.Sqrt(Math.Pow((((r_target / 1000) + (r_current / 1000)) / 2), 3) / (grav_param / 1000000000));
  return 360 * (0.5 - (T_transfer / (2 * T_target)));
  }
 
  public static double Younata_DeltaVToGetToOtherBody(double mu, double r1, double r2)
  {
  /*
  def deltaVToGetToOtherBody(mu, r1, r2):
  # mu = gravity param of common orbiting body of r1 and r2
  # (e.g. for mun to minmus, mu is kerbin's gravity param
  # r1 = initial body's orbit radius
  # r2 = target body's orbit radius
 
  # return value is km/s
  sur1 = math.sqrt(mu / r1)
  sr1r2 = math.sqrt(float(2*r2)/float(r1+r2))
  mult = sr1r2 - 1
  return sur1 * mult
  */
  double sur1, sr1r2, mult;
  sur1 = Math.Sqrt(mu / r1);
  sr1r2 = Math.Sqrt((2 * r2) / (r1 + r2));
  mult = sr1r2 - 1;
  return sur1 * mult;
  }
 
  public static double Younata_DeltaVToExitSOI(double mu, double r1, double r2, double v)
  {
  /*
  def deltaVToExitSOI(mu, r1, r2, v):
  # mu = gravity param of current body
  # r1 = current orbit radius
  # r2 = SOI radius
  # v = SOI exit velocity
  foo = r2 * (v**2) - 2 * mu
  bar = r1 * foo + (2 * r2 * mu)
  r = r1*r2
  return math.sqrt(bar / r)
  */
  double foo = r2 * Math.Pow(v, 2) - 2 * mu;
  double bar = r1 * foo + (2 * r2 * mu);
  double r = r1 * r2;
  return Math.Sqrt(bar / r);
  }
 
  public static double Younata_TransferBurnPoint(double r, double v, double angle, double mu)
  {
  /*
  def transferBurnPoint(r, v, angle, mu):
  # r = parking orbit radius
  # v = ejection velocity
  # angle = phase angle (from function phaseAngle())
  # mu = gravity param of current body.
  epsilon = ((v**2)/2) - (mu / r)
  h = r * v * math.sin(angle)
  e = math.sqrt(1 + ((2 * epsilon * h**2)/(mu**2)))
  theta = math.acos(1.0 / e)
  degrees = theta * (180.0 / math.pi)
  return 180 - degrees
  */
  double epsilon, h, ee, theta, degrees;
  epsilon = (Math.Pow(v, 2) / 2) - (mu / r);
  h = r * v * Math.Sin(angle);
  ee = Math.Sqrt(1 + ((2 * epsilon * Math.Pow(h, 2)) / Math.Pow(mu, 2)));
  theta = Math.Acos(1.0 / ee);
  degrees = theta * (180.0 / Math.PI);
  return 180 - degrees;
  // returns the ejection angle
  }
 
  public static double Adammada_CurrrentPhaseAngle(
  double body_LAN,
  double body_orbitPct,
  double origin_LAN,
  double origin_orbitPct
  )
  {
  double angle = (body_LAN / 360 + body_orbitPct) - (origin_LAN / 360 + origin_orbitPct);
  if (angle > 1)
  angle = angle - 1;
  if (angle < 0)
  angle = angle + 1;
  if (angle > 0.5)
  angle = angle - 1;
  angle = angle * 360;
  return angle;
  }
 
  public static double Adammada_CurrentEjectionAngle(
  double vessel_long,
  double origin_rotAngle,
  double origin_LAN,
  double origin_orbitPct
  )
  {
  //double eangle = ((FlightGlobals.ActiveVOID.vessel.longitude + orbiting.rotationAngle) - (orbiting.orbit.LAN / 360 + orbiting.orbit.orbitPercent) * 360);
  double eangle = ((vessel_long + origin_rotAngle) - (origin_LAN / 360 + origin_orbitPct) * 360);
 
  while (eangle < 0)
  eangle = eangle + 360;
  while (eangle > 360)
  eangle = eangle - 360;
  if (eangle < 270)
  eangle = 90 - eangle;
  else
  eangle = 450 - eangle;
  return eangle;
  }
 
  public static double mrenigma03_calcphase(Vessel vessel, CelestialBody target) //calculates phase angle between the current body and target body
  {
  Vector3d vecthis = new Vector3d();
  Vector3d vectarget = new Vector3d();
  vectarget = target.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime());
 
  if ((vessel.mainBody.name == "Sun") || (vessel.mainBody.referenceBody.referenceBody.name == "Sun"))
  {
  vecthis = vessel.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime());
  }
  else
  {
  vecthis = vessel.mainBody.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime());
  }
 
  vecthis = Vector3d.Project(new Vector3d(vecthis.x, 0, vecthis.z), vecthis);
  vectarget = Vector3d.Project(new Vector3d(vectarget.x, 0, vectarget.z), vectarget);
 
  Vector3d prograde = new Vector3d();
  prograde = Quaternion.AngleAxis(90, Vector3d.forward) * vecthis;
 
  double phase = Vector3d.Angle(vecthis, vectarget);
 
  if (Vector3d.Angle(prograde, vectarget) > 90)
  phase = 360 - phase;
 
  return (phase + 360) % 360;
  }
 
  public static double adjustCurrPhaseAngle(double transfer_angle, double curr_phase)
  {
  if (transfer_angle < 0)
  {
  if (curr_phase > 0)
  return (-1 * (360 - curr_phase));
  else if (curr_phase < 0)
  return curr_phase;
  }
  else if (transfer_angle > 0)
  {
  if (curr_phase > 0)
  return curr_phase;
  else if (curr_phase < 0)
  return (360 + curr_phase);
  }
  return curr_phase;
  }
 
  public static double adjust_current_ejection_angle(double curr_ejection)
  {
  //curr_ejection WILL need to be adjusted once for all transfers as it returns values ranging -180 to 180
  // need 0-360 instead
  //
  // ie i have -17 in the screenshot
  // need it to show 343
  //
  // do this
  //
  // if < 0, add curr to 360 // 360 + (-17) = 343
  // else its good as it is
 
  if (curr_ejection < 0)
  return 360 + curr_ejection;
  else
  return curr_ejection;
 
  }
 
  public static double adjust_transfer_ejection_angle(double trans_ejection, double trans_phase)
  {
  // if transfer_phase_angle < 0 its a lower transfer
  //180 + curr_ejection
  // else if transfer_phase_angle > 0 its good as it is
 
  if (trans_phase < 0)
  return 180 + trans_ejection;
  else
  return trans_ejection;
 
  }
 
  public static void display_transfer_angles_SUN2PLANET(CelestialBody body, Vessel vessel)
  {
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label("Phase angle (curr/trans):");
  GUILayout.Label(
  Tools.mrenigma03_calcphase(vessel, body).ToString("F3") + "° / " + Tools.Nivvy_CalcTransferPhaseAngle(
  vessel.orbit.semiMajorAxis,
  body.orbit.semiMajorAxis,
  vessel.mainBody.gravParameter
  ).ToString("F3") + "°",
  GUILayout.ExpandWidth(false)
  );
  GUILayout.EndHorizontal();
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label("Transfer velocity:");
  GUILayout.Label(
  (Tools.Younata_DeltaVToGetToOtherBody(
  (vessel.mainBody.gravParameter / 1000000000),
  (vessel.orbit.semiMajorAxis / 1000),
  (body.orbit.semiMajorAxis / 1000)
  ) * 1000).ToString("F2") + "m/s",
  GUILayout.ExpandWidth(false)
  );
  GUILayout.EndHorizontal();
  }
 
  public static void display_transfer_angles_PLANET2PLANET(CelestialBody body, Vessel vessel)
  {
  double dv1 = Tools.Younata_DeltaVToGetToOtherBody(
  (vessel.mainBody.referenceBody.gravParameter / 1000000000),
  (vessel.mainBody.orbit.semiMajorAxis / 1000),
  (body.orbit.semiMajorAxis / 1000)
  );
  double dv2 = Tools.Younata_DeltaVToExitSOI(
  (vessel.mainBody.gravParameter / 1000000000),
  (vessel.orbit.semiMajorAxis / 1000),
  (vessel.mainBody.sphereOfInfluence / 1000),
  Math.Abs(dv1)
  );
 
  double trans_ejection_angle = Tools.Younata_TransferBurnPoint(
  (vessel.orbit.semiMajorAxis / 1000),
  dv2,
  (Math.PI / 2.0),
  (vessel.mainBody.gravParameter / 1000000000)
  );
  double curr_ejection_angle = Tools.Adammada_CurrentEjectionAngle(
  FlightGlobals.ActiveVessel.longitude,
  FlightGlobals.ActiveVessel.orbit.referenceBody.rotationAngle,
  FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.LAN,
  FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.orbitPercent
  );
 
  double trans_phase_angle = Tools.Nivvy_CalcTransferPhaseAngle(
  vessel.mainBody.orbit.semiMajorAxis,
  body.orbit.semiMajorAxis,
  vessel.mainBody.referenceBody.gravParameter
  ) % 360;
  double curr_phase_angle = Tools.Adammada_CurrrentPhaseAngle(
  body.orbit.LAN,
  body.orbit.orbitPercent,
  FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.LAN,
  FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.orbitPercent
  );
 
  double adj_phase_angle = Tools.adjustCurrPhaseAngle(trans_phase_angle, curr_phase_angle);
  double adj_trans_ejection_angle = Tools.adjust_transfer_ejection_angle(trans_ejection_angle, trans_phase_angle);
  double adj_curr_ejection_angle = Tools.adjust_current_ejection_angle(curr_ejection_angle);
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label("Phase angle (curr/trans):");
  GUILayout.Label(
  adj_phase_angle.ToString("F3") + "° / " + trans_phase_angle.ToString("F3") + "°",
  GUILayout.ExpandWidth(false)
  );
  GUILayout.EndHorizontal();
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label("Ejection angle (curr/trans):");
  GUILayout.Label(
  adj_curr_ejection_angle.ToString("F3") + "° / " + adj_trans_ejection_angle.ToString("F3") + "°",
  GUILayout.ExpandWidth(false)
  );
  GUILayout.EndHorizontal();
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label("Transfer velocity:");
  GUILayout.Label((dv2 * 1000).ToString("F2") + "m/s", GUILayout.ExpandWidth(false));
  GUILayout.EndHorizontal();
  }
 
  public static void display_transfer_angles_PLANET2MOON(CelestialBody body, Vessel vessel)
  {
  double dv1 = Tools.Younata_DeltaVToGetToOtherBody(
  (vessel.mainBody.gravParameter / 1000000000),
  (vessel.orbit.semiMajorAxis / 1000),
  (body.orbit.semiMajorAxis / 1000)
  );
 
  double trans_phase_angle = Tools.Nivvy_CalcTransferPhaseAngle(
  vessel.orbit.semiMajorAxis,
  body.orbit.semiMajorAxis,
  vessel.mainBody.gravParameter
  );
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label("Phase angle (curr/trans):");
  GUILayout.Label(
  Tools.mrenigma03_calcphase(vessel, body).ToString("F3") + "° / " + trans_phase_angle.ToString("F3") + "°",
  GUILayout.ExpandWidth(false)
  );
  GUILayout.EndHorizontal();
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label("Transfer velocity:");
  GUILayout.Label((dv1 * 1000).ToString("F2") + "m/s", GUILayout.ExpandWidth(false));
  GUILayout.EndHorizontal();
  }
 
  public static void display_transfer_angles_MOON2MOON(CelestialBody body, Vessel vessel)
  {
  double dv1 = Tools.Younata_DeltaVToGetToOtherBody(
  (vessel.mainBody.referenceBody.gravParameter / 1000000000),
  (vessel.mainBody.orbit.semiMajorAxis / 1000),
  (body.orbit.semiMajorAxis / 1000)
  );
  double dv2 = Tools.Younata_DeltaVToExitSOI(
  (vessel.mainBody.gravParameter / 1000000000),
  (vessel.orbit.semiMajorAxis / 1000),
  (vessel.mainBody.sphereOfInfluence / 1000),
  Math.Abs(dv1)
  );
  double trans_ejection_angle = Tools.Younata_TransferBurnPoint(
  (vessel.orbit.semiMajorAxis / 1000),
  dv2,
  (Math.PI / 2.0),
  (vessel.mainBody.gravParameter / 1000000000)
  );
 
  double curr_phase_angle = Tools.Adammada_CurrrentPhaseAngle(
  body.orbit.LAN,
  body.orbit.orbitPercent,
  FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.LAN,
  FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.orbitPercent
  );
  double curr_ejection_angle = Tools.Adammada_CurrentEjectionAngle(
  FlightGlobals.ActiveVessel.longitude,
  FlightGlobals.ActiveVessel.orbit.referenceBody.rotationAngle,
  FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.LAN,
  FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.orbitPercent
  );
 
  double trans_phase_angle = Tools.Nivvy_CalcTransferPhaseAngle(
  vessel.mainBody.orbit.semiMajorAxis,
  body.orbit.semiMajorAxis,
  vessel.mainBody.referenceBody.gravParameter
  ) % 360;
 
  double adj_phase_angle = Tools.adjustCurrPhaseAngle(trans_phase_angle, curr_phase_angle);
  //double adj_ejection_angle = adjustCurrEjectionAngle(trans_phase_angle, curr_ejection_angle);
 
  //new stuff
  //
  double adj_trans_ejection_angle = Tools.adjust_transfer_ejection_angle(trans_ejection_angle, trans_phase_angle);
  double adj_curr_ejection_angle = Tools.adjust_current_ejection_angle(curr_ejection_angle);
  //
  //
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label("Phase angle (curr/trans):");
  GUILayout.Label(
  adj_phase_angle.ToString("F3") + "° / " + trans_phase_angle.ToString("F3") + "°",
  GUILayout.ExpandWidth(false)
  );
  GUILayout.EndHorizontal();
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label("Ejection angle (curr/trans):");
  GUILayout.Label(
  adj_curr_ejection_angle.ToString("F3") + "° / " + adj_trans_ejection_angle.ToString("F3") + "°",
  GUILayout.ExpandWidth(false)
  );
  GUILayout.EndHorizontal();
 
  GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
  GUILayout.Label("Transfer velocity:");
  GUILayout.Label((dv2 * 1000).ToString("F2") + "m/s", GUILayout.ExpandWidth(false));
  GUILayout.EndHorizontal();
  }
 
  public static string get_heading_text(double heading)
  {
  if (heading > 348.75 || heading <= 11.25)
  return "N";
  else if (heading > 11.25 && heading <= 33.75)
  return "NNE";
  else if (heading > 33.75 && heading <= 56.25)
  return "NE";
  else if (heading > 56.25 && heading <= 78.75)
  return "ENE";
  else if (heading > 78.75 && heading <= 101.25)
  return "E";
  else if (heading > 101.25 && heading <= 123.75)
  return "ESE";
  else if (heading > 123.75 && heading <= 146.25)
  return "SE";
  else if (heading > 146.25 && heading <= 168.75)
  return "SSE";
  else if (heading > 168.75 && heading <= 191.25)
  return "S";
  else if (heading > 191.25 && heading <= 213.75)
  return "SSW";
  else if (heading > 213.75 && heading <= 236.25)
  return "SW";
  else if (heading > 236.25 && heading <= 258.75)
  return "WSW";
  else if (heading > 258.75 && heading <= 281.25)
  return "W";
  else if (heading > 281.25 && heading <= 303.75)
  return "WNW";
  else if (heading > 303.75 && heading <= 326.25)
  return "NW";
  else if (heading > 326.25 && heading <= 348.75)
  return "NNW";
  else
  return "";
  }
  }
  }
 
 
// //
// 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 ToadicusTools;
using UnityEngine; using UnityEngine;
   
namespace VOID namespace VOID
{ {
public class VOID_Transfer : VOID_WindowModule public class VOID_Transfer : VOID_WindowModule
{ {
protected List<CelestialBody> selectedBodies = new List<CelestialBody>(); protected List<CelestialBody> selectedBodies = new List<CelestialBody>();
   
public VOID_Transfer() public VOID_Transfer()
{ {
this._Name = "Transfer Angle Information"; this._Name = "Transfer Angle Information";
   
this.WindowPos.x = 475; this.WindowPos.x = 475;
this.WindowPos.y = 85; this.WindowPos.y = 85;
this.defWidth = 315; this.defWidth = 315;
} }
   
public override void ModuleWindow(int _) public override void ModuleWindow(int _)
{ {
GUILayout.BeginVertical(); GUILayout.BeginVertical();
   
if (vessel.mainBody.name == "Sun") //Vessel is orbiting the Sun if (vessel.mainBody.name == "Sun") //Vessel is orbiting the Sun
{ {
foreach (CelestialBody body in vessel.mainBody.orbitingBodies) foreach (CelestialBody body in vessel.mainBody.orbitingBodies)
{ {
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
if (GUILayout.Button(body.bodyName)) if (GUILayout.Button(body.bodyName))
{ {
//add or remove this body to this list of bodies to display more info on //add or remove this body to this list of bodies to display more info on
if (selectedBodies.Contains(body)) selectedBodies.Remove(body); if (selectedBodies.Contains(body)) selectedBodies.Remove(body);
else selectedBodies.Add(body); else selectedBodies.Add(body);
} }
GUILayout.Label("Inclined " + body.orbit.inclination.ToString("F3") + "°", GUILayout.ExpandWidth(false)); GUILayout.Label("Inclined " + body.orbit.inclination.ToString("F3") + "°", GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
if (selectedBodies.Contains(body)) if (selectedBodies.Contains(body))
{ {
Tools.display_transfer_angles_SUN2PLANET(body, vessel); //show phase angles for each selected body Tools.display_transfer_angles_SUN2PLANET(body, vessel); //show phase angles for each selected body
tad_targeting(body); //display Set/Unset Target button for each selected body tad_targeting(body); //display Set/Unset Target button for each selected body
} }
} }
} }
else if (vessel.mainBody.referenceBody.name == "Sun") //Vessel is orbiting a planet else if (vessel.mainBody.referenceBody.name == "Sun") //Vessel is orbiting a planet
{ {
foreach (CelestialBody body in vessel.mainBody.referenceBody.orbitingBodies) foreach (CelestialBody body in vessel.mainBody.referenceBody.orbitingBodies)
{ {
if (body.name != vessel.mainBody.name) // show other planets if (body.name != vessel.mainBody.name) // show other planets
{ {
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
if (GUILayout.Button(body.bodyName)) if (GUILayout.Button(body.bodyName))
{ {
//add or remove this body to this list of bodies to display more info on //add or remove this body to this list of bodies to display more info on
if (selectedBodies.Contains(body)) selectedBodies.Remove(body); if (selectedBodies.Contains(body)) selectedBodies.Remove(body);
else selectedBodies.Add(body); else selectedBodies.Add(body);
} }
GUILayout.Label("Inclined " + body.orbit.inclination.ToString("F3") + "°", GUILayout.ExpandWidth(false)); GUILayout.Label("Inclined " + body.orbit.inclination.ToString("F3") + "°", GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
if (selectedBodies.Contains(body)) if (selectedBodies.Contains(body))
{ {
Tools.display_transfer_angles_PLANET2PLANET(body, vessel); Tools.display_transfer_angles_PLANET2PLANET(body, vessel);
tad_targeting(body); //display Set/Unset Target button tad_targeting(body); //display Set/Unset Target button
} }
} }
} }
foreach (CelestialBody body in vessel.mainBody.orbitingBodies) // show moons foreach (CelestialBody body in vessel.mainBody.orbitingBodies) // show moons
{ {
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
if (GUILayout.Button(body.bodyName)) if (GUILayout.Button(body.bodyName))
{ {
//add or remove this body to this list of bodies to display more info on //add or remove this body to this list of bodies to display more info on
if (selectedBodies.Contains(body)) selectedBodies.Remove(body); if (selectedBodies.Contains(body)) selectedBodies.Remove(body);
else selectedBodies.Add(body); else selectedBodies.Add(body);
} }
GUILayout.Label("Inclined " + body.orbit.inclination.ToString("F3") + "°", GUILayout.ExpandWidth(false)); GUILayout.Label("Inclined " + body.orbit.inclination.ToString("F3") + "°", GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
if (selectedBodies.Contains(body)) if (selectedBodies.Contains(body))
{ {
Tools.display_transfer_angles_PLANET2MOON(body, vessel); Tools.display_transfer_angles_PLANET2MOON(body, vessel);
tad_targeting(body); //display Set/Unset Target button tad_targeting(body); //display Set/Unset Target button
} }
} }
} }
else if (vessel.mainBody.referenceBody.referenceBody.name == "Sun") // Vessel is orbiting a moon else if (vessel.mainBody.referenceBody.referenceBody.name == "Sun") // Vessel is orbiting a moon
{ {
foreach (CelestialBody body in vessel.mainBody.referenceBody.orbitingBodies) foreach (CelestialBody body in vessel.mainBody.referenceBody.orbitingBodies)
{ {
if (body.name != vessel.mainBody.name) // show other moons if (body.name != vessel.mainBody.name) // show other moons
{ {
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
if (GUILayout.Button(body.bodyName)) if (GUILayout.Button(body.bodyName))
{ {
//add or remove this body to this list of bodies to display more info on //add or remove this body to this list of bodies to display more info on
if (selectedBodies.Contains(body)) selectedBodies.Remove(body); if (selectedBodies.Contains(body)) selectedBodies.Remove(body);
else selectedBodies.Add(body); else selectedBodies.Add(body);
} }
GUILayout.Label("Inclined " + body.orbit.inclination.ToString("F3") + "°", GUILayout.ExpandWidth(false)); GUILayout.Label("Inclined " + body.orbit.inclination.ToString("F3") + "°", GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
if (selectedBodies.Contains(body)) if (selectedBodies.Contains(body))
{ {
Tools.display_transfer_angles_MOON2MOON(body, vessel); Tools.display_transfer_angles_MOON2MOON(body, vessel);
tad_targeting(body); //display Set/Unset Target button tad_targeting(body); //display Set/Unset Target button
} }
} }
} }
} }
GUILayout.EndVertical(); GUILayout.EndVertical();
GUI.DragWindow(); GUI.DragWindow();
} }
   
private void tad_targeting(CelestialBody body) private void tad_targeting(CelestialBody body)
{ {
//Target Set/Unset buttons //Target Set/Unset buttons
if (FlightGlobals.fetch.VesselTarget == null || (FlightGlobals.fetch.VesselTarget != null && FlightGlobals.fetch.VesselTarget.GetVessel() == null)) if (FlightGlobals.fetch.VesselTarget == null || (FlightGlobals.fetch.VesselTarget != null && FlightGlobals.fetch.VesselTarget.GetVessel() == null))
{ {
//No TGT set or TGT is a Body //No TGT set or TGT is a Body
if ((CelestialBody)FlightGlobals.fetch.VesselTarget != body) if ((CelestialBody)FlightGlobals.fetch.VesselTarget != body)
{ {
if (GUILayout.Button("Set Target", GUILayout.ExpandWidth(false))) if (GUILayout.Button("Set Target", GUILayout.ExpandWidth(false)))
{ {
FlightGlobals.fetch.SetVesselTarget(body); FlightGlobals.fetch.SetVesselTarget(body);
Tools.PostDebugMessage("[VOID] KSP Target set to CelestialBody " + body.bodyName); Tools.PostDebugMessage("[VOID] KSP Target set to CelestialBody " + body.bodyName);
} }
} }
else if ((CelestialBody)FlightGlobals.fetch.VesselTarget == body) else if ((CelestialBody)FlightGlobals.fetch.VesselTarget == body)
{ {
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] KSP Target set to null"); Tools.PostDebugMessage("[VOID] KSP Target set to null");
} }
} }
} }
else if (FlightGlobals.fetch.VesselTarget == null || (FlightGlobals.fetch.VesselTarget != null && FlightGlobals.fetch.VesselTarget.GetVessel() != null)) else if (FlightGlobals.fetch.VesselTarget == null || (FlightGlobals.fetch.VesselTarget != null && FlightGlobals.fetch.VesselTarget.GetVessel() != null))
{ {
//No TGT or TGT is a vessel //No TGT or TGT is a vessel
if (GUILayout.Button("Set Target", GUILayout.ExpandWidth(false))) if (GUILayout.Button("Set Target", GUILayout.ExpandWidth(false)))
{ {
FlightGlobals.fetch.SetVesselTarget(body); FlightGlobals.fetch.SetVesselTarget(body);
Tools.PostDebugMessage("[VOID] KSP Target set to CelestialBody " + body.bodyName); Tools.PostDebugMessage("[VOID] KSP Target set to CelestialBody " + body.bodyName);
} }
} }
} }
} }
} }
   
   
// //
// 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; 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( public VOID_VesselInfo() : base()
  {
  this._Name = "Vessel Information";
   
  this.WindowPos.x = Screen.width - 260;
  this.WindowPos.y = 450;
  }
   
  public override void ModuleWindow(int _)
  {
  base.ModuleWindow (_);
   
  if ((TimeWarp.WarpMode == TimeWarp.Modes.LOW) || (TimeWarp.CurrentRate <= TimeWarp.MaxPhysicsRate))
  {
  SimManager.RequestSimulation();
  }
   
  GUILayout.BeginVertical();
   
  GUILayout.Label(
  vessel.vesselName,
  VOID_Core.Instance.LabelStyles["center_bold"],
  GUILayout.ExpandWidth(true));
   
  VOID_Data.geeForce.DoGUIHorizontal ("F2");
   
  VOID_Data.partCount.DoGUIHorizontal ();
   
  VOID_Data.totalMass.DoGUIHorizontal ("F1");
   
  VOID_Data.resourceMass.DoGUIHorizontal ("F1");
   
  VOID_Data.stageDeltaV.DoGUIHorizontal (3, false);
   
  VOID_Data.totalDeltaV.DoGUIHorizontal (3, false);
   
  VOID_Data.mainThrottle.DoGUIHorizontal ("F0");
   
  VOID_Data.currmaxThrust.DoGUIHorizontal ();
   
  VOID_Data.currmaxThrustWeight.DoGUIHorizontal ();
   
  VOID_Data.surfaceThrustWeight.DoGUIHorizontal ("F2");
   
  VOID_Data.intakeAirStatus.DoGUIHorizontal();
   
  GUILayout.EndVertical();
   
  GUI.DragWindow();
  }
  }
   
  public static partial class VOID_Data
  {
  public static readonly 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( public static readonly 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( public static readonly VOID_DoubleValue totalMass = new VOID_DoubleValue(
"Total Mass", "Total Mass",
new Func<double>(() => VOID_Core.Instance.vessel.GetTotalMass()), delegate()
  {
  if (SimManager.LastStage == null)
  {
  return double.NaN;
  }
   
  return SimManager.LastStage.totalMass;
  },
"tons" "tons"
); );
   
protected VOID_DoubleValue resourceMass = new VOID_DoubleValue( public static readonly 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( public static readonly VOID_DoubleValue stageDeltaV = new VOID_DoubleValue(
"DeltaV (Current Stage)", "DeltaV (Current Stage)",
delegate() delegate()
{ {
if (SimManager.Instance.Stages == null || if (SimManager.Stages == null ||
SimManager.Instance.Stages.Length <= Staging.lastStage SimManager.Stages.Length <= Staging.lastStage
) )
return double.NaN; return double.NaN;
return SimManager.Instance.Stages[Staging.lastStage].deltaV; return SimManager.Stages[Staging.lastStage].deltaV;
}, },
"m/s" "m/s"
); );
   
protected VOID_DoubleValue totalDeltaV = new VOID_DoubleValue( public static readonly VOID_DoubleValue totalDeltaV = new VOID_DoubleValue(
"DeltaV (Total)", "DeltaV (Total)",
delegate() delegate()
{ {
if (SimManager.Instance.Stages == null) if (SimManager.Stages == null)
return double.NaN; return double.NaN;
return SimManager.Instance.LastStage.totalDeltaV; return SimManager.LastStage.totalDeltaV;
}, },
"m/s" "m/s"
); );
   
protected VOID_FloatValue mainThrottle = new VOID_FloatValue( public static readonly 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( public static readonly VOID_StrValue currmaxThrust = new VOID_StrValue(
"Thrust (curr/max)", "Thrust (curr/max)",
delegate() delegate()
{ {
if (SimManager.Instance.Stages == null) if (SimManager.Stages == null)
return "N/A"; return "N/A";
   
double currThrust = SimManager.Instance.LastStage.actualThrust; double currThrust = SimManager.LastStage.actualThrust;
double maxThrust = SimManager.Instance.LastStage.thrust; double maxThrust = SimManager.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( public static readonly VOID_StrValue currmaxThrustWeight = new VOID_StrValue(
"T:W (curr/max)", "T:W (curr/max)",
delegate() delegate()
{ {
if (SimManager.Instance.Stages == null) if (SimManager.Stages == null || SimManager.LastStage == null)
return "N/A"; return "N/A";
   
double currThrust = SimManager.Instance.LastStage.actualThrust; double currThrust = SimManager.LastStage.actualThrust;
double maxThrust = SimManager.Instance.LastStage.thrust; double maxThrust = SimManager.LastStage.thrust;
double mass = VOID_Core.Instance.vessel.GetTotalMass(); double mass = SimManager.LastStage.totalMass;
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( public static readonly VOID_DoubleValue surfaceThrustWeight = new VOID_DoubleValue(
"Max T:W @ surface", "Max T:W @ surface",
delegate() delegate()
{ {
if (SimManager.Instance.Stages == null) if (SimManager.Stages == null || SimManager.LastStage == null)
return double.NaN; return double.NaN;
   
double maxThrust = SimManager.Instance.LastStage.thrust; double maxThrust = SimManager.LastStage.thrust;
double mass = VOID_Core.Instance.vessel.GetTotalMass(); double mass = SimManager.LastStage.totalMass;
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( public static readonly VOID_StrValue intakeAirStatus = new VOID_StrValue(
"Intake Air (Curr / Req)", "Intake Air (Curr / Req)",
delegate() delegate()
{ {
double currentAmount; double currentAmount;
double currentRequirement; double currentRequirement;
   
currentAmount = 0d; currentAmount = 0d;
currentRequirement = 0d; currentRequirement = 0d;
   
foreach (Part part in VOID_Core.Instance.vessel.Parts) foreach (Part part in VOID_Core.Instance.vessel.Parts)
{ {
if (part.HasModule<ModuleEngines>() && part.enabled) if (part.HasModule<ModuleEngines>() && part.enabled)
{ {
foreach (Propellant propellant in part.GetModule<ModuleEngines>().propellants) foreach (Propellant propellant in part.GetModule<ModuleEngines>().propellants)
{ {
if (propellant.name == "IntakeAir") if (propellant.name == "IntakeAir")
{ {
// currentAmount += propellant.currentAmount; // currentAmount += propellant.currentAmount;
currentRequirement += propellant.currentRequirement / TimeWarp.fixedDeltaTime; currentRequirement += propellant.currentRequirement / TimeWarp.fixedDeltaTime;
break; break;
} }
} }
} }
   
if (part.HasModule<ModuleResourceIntake>() && part.enabled) if (part.HasModule<ModuleResourceIntake>() && part.enabled)
{ {
ModuleResourceIntake intakeModule = part.GetModule<ModuleResourceIntake>(); ModuleResourceIntake intakeModule = part.GetModule<ModuleResourceIntake>();
   
if (intakeModule.resourceName == "IntakeAir") if (intakeModule.resourceName == "IntakeAir")
{ {
currentAmount += intakeModule.airFlow; currentAmount += intakeModule.airFlow;
} }
} }
} }
   
if (currentAmount == 0 && currentRequirement == 0) if (currentAmount == 0 && currentRequirement == 0)
{ {
return "N/A"; return "N/A";
} }
   
return string.Format("{0:F3} / {1:F3}", currentAmount, currentRequirement); return string.Format("{0:F3} / {1:F3}", currentAmount, currentRequirement);
} }
); );
   
public VOID_VesselInfo() : base()  
{  
this._Name = "Vessel Information";  
   
this.WindowPos.x = Screen.width - 260;  
this.WindowPos.y = 450;  
}  
   
public override void ModuleWindow(int _)  
{  
base.ModuleWindow (_);  
   
if ((TimeWarp.WarpMode == TimeWarp.Modes.LOW) || (TimeWarp.CurrentRate <= TimeWarp.MaxPhysicsRate))  
{  
SimManager.Instance.RequestSimulation();  
}  
   
Stage[] stages = SimManager.Instance.Stages;  
   
GUILayout.BeginVertical();  
   
GUILayout.Label(  
vessel.vesselName,  
VOID_Core.Instance.LabelStyles["center_bold"],  
GUILayout.ExpandWidth(true));  
   
this.geeForce.DoGUIHorizontal ("F2");  
   
this.partCount.DoGUIHorizontal ();  
   
this.totalMass.DoGUIHorizontal ("F1");  
   
this.resourceMass.DoGUIHorizontal ("F1");  
   
this.stageDeltaV.DoGUIHorizontal (3, false);  
   
this.totalDeltaV.DoGUIHorizontal (3, false);  
   
this.mainThrottle.DoGUIHorizontal ("F0");  
   
this.currmaxThrust.DoGUIHorizontal ();  
   
this.currmaxThrustWeight.DoGUIHorizontal ();  
   
this.surfaceThrustWeight.DoGUIHorizontal ("F2");  
   
this.intakeAirStatus.DoGUIHorizontal();  
   
GUILayout.EndVertical();  
GUI.DragWindow();  
}  
} }
} }
   
   
// //
// 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.Linq; using System.Linq;
  using ToadicusTools;
using UnityEngine; using UnityEngine;
   
namespace VOID namespace VOID
{ {
public class VOID_VesselRegister : VOID_WindowModule public class VOID_VesselRegister : VOID_WindowModule
{ {
[AVOID_SaveValue("selectedBodyIdx")] [AVOID_SaveValue("selectedBodyIdx")]
protected VOID_SaveValue<int> selectedBodyIdx = 0; protected VOID_SaveValue<int> selectedBodyIdx = 0;
protected CelestialBody seletedBody; protected CelestialBody seletedBody;
   
[AVOID_SaveValue("selectedVesselTypeIdx")] [AVOID_SaveValue("selectedVesselTypeIdx")]
protected VOID_SaveValue<int> selectedVesselTypeIdx = 0; protected VOID_SaveValue<int> selectedVesselTypeIdx = 0;
protected VesselType selectedVesselType; protected VesselType selectedVesselType;
   
protected string vesselSituation = "Orbiting"; protected string vesselSituation = "Orbiting";
   
protected Vector2 selectorScrollPos = new Vector2(); protected Vector2 selectorScrollPos = new Vector2();
   
protected Vessel _selectedVessel; protected Vessel _selectedVessel;
   
public Vessel selectedVessel public Vessel selectedVessel
{ {
get get
{ {
return this._selectedVessel; return this._selectedVessel;
} }
} }
   
public VOID_VesselRegister() public VOID_VesselRegister()
{ {
this._Name = "Vessel Register"; this._Name = "Vessel Register";
   
this.WindowPos.x = 845; this.WindowPos.x = 845;
this.WindowPos.y = 275; this.WindowPos.y = 275;
this.defHeight = 375; this.defHeight = 375;
} }
   
public override void ModuleWindow(int _) public override void ModuleWindow(int _)
{ {
if (!VOID_Core.Instance.allVesselTypes.Any()) if (!VOID_Core.Instance.allVesselTypes.Any())
{ {
return; return;
} }
   
GUILayout.BeginVertical(); GUILayout.BeginVertical();
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
if (GUILayout.Button("<")) if (GUILayout.Button("<"))
{ {
selectedBodyIdx--; selectedBodyIdx--;
if (selectedBodyIdx < 0) selectedBodyIdx = VOID_Core.Instance.allBodies.Count - 1; if (selectedBodyIdx < 0) selectedBodyIdx = VOID_Core.Instance.allBodies.Count - 1;
} }
GUILayout.Label(VOID_Core.Instance.allBodies[selectedBodyIdx].bodyName, VOID_Core.Instance.LabelStyles["center_bold"], GUILayout.ExpandWidth(true)); GUILayout.Label(VOID_Core.Instance.allBodies[selectedBodyIdx].bodyName, VOID_Core.Instance.LabelStyles["center_bold"], GUILayout.ExpandWidth(true));
if (GUILayout.Button(">")) if (GUILayout.Button(">"))
{ {
selectedBodyIdx++; selectedBodyIdx++;
if (selectedBodyIdx > VOID_Core.Instance.allBodies.Count - 1) selectedBodyIdx = 0; if (selectedBodyIdx > VOID_Core.Instance.allBodies.Count - 1) selectedBodyIdx = 0;
} }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
seletedBody = VOID_Core.Instance.allBodies[selectedBodyIdx]; seletedBody = VOID_Core.Instance.allBodies[selectedBodyIdx];
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
if (GUILayout.Button("<")) if (GUILayout.Button("<"))
{ {
selectedVesselTypeIdx--; selectedVesselTypeIdx--;
if (selectedVesselTypeIdx < 0) selectedVesselTypeIdx = VOID_Core.Instance.allVesselTypes.Count - 1; if (selectedVesselTypeIdx < 0) selectedVesselTypeIdx = VOID_Core.Instance.allVesselTypes.Count - 1;
} }
GUILayout.Label(VOID_Core.Instance.allVesselTypes[selectedVesselTypeIdx].ToString(), VOID_Core.Instance.LabelStyles["center_bold"], GUILayout.ExpandWidth(true)); GUILayout.Label(VOID_Core.Instance.allVesselTypes[selectedVesselTypeIdx].ToString(), VOID_Core.Instance.LabelStyles["center_bold"], GUILayout.ExpandWidth(true));
if (GUILayout.Button(">")) if (GUILayout.Button(">"))
{ {
selectedVesselTypeIdx++; selectedVesselTypeIdx++;
if (selectedVesselTypeIdx > VOID_Core.Instance.allVesselTypes.Count - 1) selectedVesselTypeIdx = 0; if (selectedVesselTypeIdx > VOID_Core.Instance.allVesselTypes.Count - 1) selectedVesselTypeIdx = 0;
} }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
selectedVesselType = VOID_Core.Instance.allVesselTypes[selectedVesselTypeIdx]; selectedVesselType = VOID_Core.Instance.allVesselTypes[selectedVesselTypeIdx];
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
if (GUILayout.Button("Landed", GUILayout.ExpandWidth(true))) vesselSituation = "Landed"; if (GUILayout.Button("Landed", GUILayout.ExpandWidth(true))) vesselSituation = "Landed";
if (GUILayout.Button("Orbiting", GUILayout.ExpandWidth(true))) vesselSituation = "Orbiting"; if (GUILayout.Button("Orbiting", GUILayout.ExpandWidth(true))) vesselSituation = "Orbiting";
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label( GUILayout.Label(
Tools.UppercaseFirst(vesselSituation) + " " + selectedVesselType.ToString() + "s @ " + seletedBody.bodyName, Tools.UppercaseFirst(vesselSituation) + " " + selectedVesselType.ToString() + "s @ " + seletedBody.bodyName,
VOID_Core.Instance.LabelStyles["center"], VOID_Core.Instance.LabelStyles["center"],
GUILayout.ExpandWidth(true)); GUILayout.ExpandWidth(true));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
selectorScrollPos = GUILayout.BeginScrollView(selectorScrollPos, false, false); selectorScrollPos = GUILayout.BeginScrollView(selectorScrollPos, false, false);
   
foreach (Vessel v in FlightGlobals.Vessels) foreach (Vessel v in FlightGlobals.Vessels)
{ {
if (v != vessel && v.vesselType == selectedVesselType && v.mainBody == seletedBody) if (v != vessel && v.vesselType == selectedVesselType && v.mainBody == seletedBody)
{ {
if ((vesselSituation == "Landed" && if ((vesselSituation == "Landed" &&
(v.situation == Vessel.Situations.LANDED || (v.situation == Vessel.Situations.LANDED ||
v.situation == Vessel.Situations.PRELAUNCH || v.situation == Vessel.Situations.PRELAUNCH ||
v.situation == Vessel.Situations.SPLASHED)) || v.situation == Vessel.Situations.SPLASHED)) ||
(vesselSituation == "Orbiting" && (vesselSituation == "Orbiting" &&
(v.situation == Vessel.Situations.ESCAPING || (v.situation == Vessel.Situations.ESCAPING ||
v.situation == Vessel.Situations.FLYING || v.situation == Vessel.Situations.FLYING ||
v.situation == Vessel.Situations.ORBITING || v.situation == Vessel.Situations.ORBITING ||
v.situation == Vessel.Situations.SUB_ORBITAL)) v.situation == Vessel.Situations.SUB_ORBITAL))
) )
{ {
if (GUILayout.Button(v.vesselName, GUILayout.ExpandWidth(true))) if (GUILayout.Button(v.vesselName, GUILayout.ExpandWidth(true)))
{ {
if (_selectedVessel != v) if (_selectedVessel != v)
{ {
_selectedVessel = v; //set clicked vessel as selected_vessel _selectedVessel = v; //set clicked vessel as selected_vessel
this._Active.value = true; //turn bool on to open the window if closed this._Active.value = true; //turn bool on to open the window if closed
} }
else else
{ {
_selectedVessel = null; _selectedVessel = null;
} }
} }
} }
} }
} }
   
GUILayout.EndScrollView(); GUILayout.EndScrollView();
   
GUILayout.EndVertical(); GUILayout.EndVertical();
   
GUI.DragWindow(); GUI.DragWindow();
} }
} }
} }