VOID_Data: Resource mass values reverted to use VesselSimulator's fields again.
VOID_Data: Resource mass values reverted to use VesselSimulator's fields again.

--- /dev/null
+++ b/API/VOID_SingletonCore.cs
@@ -1,1 +1,69 @@
+// VOID
+//
+// VOID_SingletonModule.cs
+//
+// Copyright © 2015, toadicus
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+//    this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation and/or other
+//    materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its contributors may be used
+//    to endorse or promote products derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+using System;
 
+namespace VOID
+{
+	public abstract class VOID_SingletonCore<T> : VOIDCore, IVOID_Module, IDisposable
+		where T : VOID_Module, new()
+	{
+		#region Singleton Members
+		/*
+		 * Static Members
+		 * */
+		protected static bool _initialized = false;
+
+		public static bool Initialized
+		{
+			get
+			{
+				return _initialized;
+			}
+		}
+
+		protected static T _instance;
+
+		public static T Instance
+		{
+			get
+			{
+				if (_instance == null)
+				{
+					_instance = new T();
+					_initialized = true;
+				}
+				return _instance;
+			}
+		}
+
+		public abstract void Dispose();
+		#endregion
+	}
+}
+
+

--- a/API/VOID_SingletonModule.cs
+++ /dev/null
@@ -1,67 +1,1 @@
-// VOID
-//
-// VOID_SingletonModule.cs
-//
-// Copyright © 2015, toadicus
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without modification,
-// are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice,
-//    this list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-//    this list of conditions and the following disclaimer in the documentation and/or other
-//    materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its contributors may be used
-//    to endorse or promote products derived from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
-// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-using System;
 
-namespace VOID
-{
-	public abstract class VOID_SingletonModule<T> : VOIDCore, IVOID_Module
-		where T : VOID_Module, new()
-	{
-		#region Singleton Members
-		/*
-		 * Static Members
-		 * */
-		protected static bool _initialized = false;
-
-		public static bool Initialized
-		{
-			get
-			{
-				return _initialized;
-			}
-		}
-
-		protected static T _instance;
-
-		public static T Instance
-		{
-			get
-			{
-				if (_instance == null)
-				{
-					_instance = new T();
-					_initialized = true;
-				}
-				return _instance;
-			}
-		}
-		#endregion
-	}
-}
-
-

--- /dev/null
+++ b/API/VOID_SingletonWindow.cs
@@ -1,1 +1,73 @@
+// VOID
+//
+// VOID_SingletonModule.cs
+//
+// Copyright © 2015, toadicus
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+//    this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation and/or other
+//    materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its contributors may be used
+//    to endorse or promote products derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+using System;
 
+namespace VOID
+{
+	public abstract class VOID_SingletonWindow<T> : VOID_WindowModule, IVOID_Module, IDisposable
+		where T : VOID_WindowModule, new()
+	{
+		#region Singleton Members
+		/*
+		 * Static Members
+		 * */
+		protected static bool _initialized = false;
+
+		public static bool Initialized
+		{
+			get
+			{
+				return _initialized;
+			}
+		}
+
+		protected static T _instance;
+
+		public static T Instance
+		{
+			get
+			{
+				if (_instance == null)
+				{
+					_instance = new T();
+					_initialized = true;
+				}
+				return _instance;
+			}
+		}
+
+		public virtual void Dispose()
+		{
+			_instance = null;
+			_initialized = false;
+		}
+		#endregion
+	}
+}
+
+

--- a/VOID.csproj
+++ b/VOID.csproj
@@ -106,7 +106,6 @@
     <Compile Include="Tools\VOID_DataValue.cs" />
     <Compile Include="Tools\VOID_SaveValue.cs" />
     <Compile Include="API\VOID_HUDModule.cs" />
-    <Compile Include="API\VOID_SingletonModule.cs" />
     <Compile Include="API\Attributes\VOID_ScenesAttribute.cs" />
     <Compile Include="API\Attributes\AVOID_SaveValue.cs" />
     <Compile Include="API\VOIDMaster.cs" />
@@ -114,6 +113,8 @@
     <Compile Include="VOID_ConfigWindow.cs" />
     <Compile Include="Tools\VOID_Localization.cs" />
     <Compile Include="Tools\VOID_StageExtensions.cs" />
+    <Compile Include="API\VOID_SingletonCore.cs" />
+    <Compile Include="API\VOID_SingletonWindow.cs" />
   </ItemGroup>
   <ProjectExtensions>
     <MonoDevelop>

--- a/VOIDCore_Generic.cs
+++ b/VOIDCore_Generic.cs
@@ -37,7 +37,7 @@
 
 namespace VOID
 {
-	public abstract class VOIDCore_Generic<T> : VOID_SingletonModule<T>, IVOID_Module, IDisposable
+	public abstract class VOIDCore_Generic<T> : VOID_SingletonCore<T>, IVOID_Module, IDisposable
 		where T : VOID_Module, new()
 	{
 		/*
@@ -119,14 +119,29 @@
 
 		public override bool configDirty { get; set; }
 
-		internal IButton ToolbarButton;
-
-		internal ApplicationLauncherButton AppLauncherButton;
+		protected IButton ToolbarButton;
+		protected ApplicationLauncherButton AppLauncherButton;
+		protected IconState iconState;
 
 		/*
 		 * Properties
 		 * */
-
+		public override bool Active
+		{
+			get
+			{
+				return base.Active;
+			}
+			set
+			{
+				if (value != base.Active)
+				{
+					this.SetIconTexture(this.powerState | this.activeState);
+				}
+
+				base.Active = value;
+			}
+		}
 		public override IList<CelestialBody> AllBodies
 		{
 			get
@@ -372,6 +387,8 @@
 				);
 				this.InitializeToolbarButton();
 			}
+
+			this.SetIconTexture();
 
 			if (this.Active)
 			{
@@ -470,7 +487,6 @@
 				if (this.powerAvailable != newPowerState)
 				{
 					this.powerAvailable = newPowerState;
-					this.SetIconTexture(this.powerState | this.activeState);
 				}
 			}
 
@@ -541,7 +557,6 @@
 					if (GUILayout.Button("Power " + str))
 					{
 						togglePower.value = !togglePower;
-						this.SetIconTexture(this.powerState | this.activeState);
 					}
 				}
 
@@ -753,7 +768,9 @@
 
 			var InstanceProperty = T.GetProperty(
 				"Instance",
-				System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public
+				System.Reflection.BindingFlags.Static |
+				System.Reflection.BindingFlags.Public |
+				System.Reflection.BindingFlags.FlattenHierarchy
 			);
 
 			object modInstance = null;
@@ -783,6 +800,13 @@
 						this.GetType().Name,
 						T.Name
 					));
+			}
+			else
+			{
+				if (module is IDisposable)
+				{
+					(module as IDisposable).Dispose();
+				}
 			}
 		}
 
@@ -928,7 +952,19 @@
 		protected void ToggleMainWindow()
 		{
 			this.Active = !this.Active;
-			this.SetIconTexture(this.powerState | this.activeState);
+		}
+
+		protected void SetIconTexture()
+		{
+			if (
+				this.iconState != (this.powerState | this.activeState) ||
+				(this.VOIDIconTexture == null && this.AppLauncherButton != null)
+			)
+			{
+				this.iconState = this.powerState | this.activeState;
+
+				this.SetIconTexture(this.iconState);
+			}
 		}
 
 		protected void SetIconTexture(IconState state)
@@ -954,15 +990,20 @@
 
 		protected void SetIconTexture(string texturePath)
 		{
+			if (texturePath == null)
+			{
+				return;
+			}
+
 			if (this.ToolbarButton != null)
 			{
 				this.ToolbarButton.TexturePath = texturePath;
 			}
 
-			this.VOIDIconTexture = GameDatabase.Instance.GetTexture(texturePath.Replace("icon", "appIcon"), false);
-
 			if (this.AppLauncherButton != null)
 			{
+				this.VOIDIconTexture = GameDatabase.Instance.GetTexture(texturePath.Replace("icon", "appIcon"), false);
+
 				this.AppLauncherButton.SetTexture(VOIDIconTexture);
 			}
 		}
@@ -1054,13 +1095,11 @@
 			this.LoadConfig();
 
 			this.configVersion = (VOID_SaveValue<int>)VOIDCore.CONFIG_VERSION;
-			
-			this.SetIconTexture(this.powerState | this.activeState);
 
 			this.FactoryReset = false;
 		}
 
-		public virtual void Dispose()
+		public override void Dispose()
 		{
 			this.StopGUI();
 

--- a/VOID_CareerStatus.cs
+++ b/VOID_CareerStatus.cs
@@ -36,14 +36,8 @@
 {
 	[VOID_Scenes(GameScenes.FLIGHT, GameScenes.EDITOR, GameScenes.SPACECENTER)]
 	[VOID_GameModes(Game.Modes.CAREER, Game.Modes.SCIENCE_SANDBOX)]
-	public class VOID_CareerStatus : VOID_WindowModule
+	public class VOID_CareerStatus : VOID_SingletonWindow<VOID_CareerStatus>
 	{
-		public static VOID_CareerStatus Instance
-		{
-			get;
-			private set;
-		}
-
 		public static string formatDelta(double delta, string numberFormat)
 		{
 			if (delta > 0)
@@ -233,11 +227,6 @@
 		 * */
 		public VOID_CareerStatus() : base()
 		{
-			if (this.InValidGame && this.InValidScene)
-			{
-				VOID_CareerStatus.Instance = this;
-			}
-
 			this.Name = "Career Status";
 
 			GameEvents.OnFundsChanged.Add(this.onFundsChange);
@@ -269,14 +258,19 @@
 			this.currentReputation = float.NaN;
 		}
 
-		~VOID_CareerStatus()
+		public override void Dispose()
 		{
 			GameEvents.OnFundsChanged.Remove(this.onFundsChange);
 			GameEvents.OnReputationChanged.Remove(this.onRepChange);
 			GameEvents.OnScienceChanged.Remove(this.onScienceChange);
 			GameEvents.onGameStateLoad.Remove(this.onGameStateLoad);
 
-			VOID_CareerStatus.Instance = null;
+			base.Dispose();
+		}
+
+		~VOID_CareerStatus()
+		{
+			this.Dispose();
 		}
 	}
 }

--- a/VOID_ConfigWindow.cs
+++ b/VOID_ConfigWindow.cs
@@ -33,14 +33,8 @@
 
 namespace VOID
 {
-	public class VOID_ConfigWindow : VOID_WindowModule
+	public class VOID_ConfigWindow : VOID_SingletonWindow<VOID_ConfigWindow>
 	{
-		public static VOID_ConfigWindow Instance
-		{
-			get;
-			private set;
-		}
-
 		public override bool InValidScene
 		{
 			get
@@ -59,8 +53,6 @@
 
 		public VOID_ConfigWindow() : base()
 		{
-			VOID_ConfigWindow.Instance = this;
-
 			this.Name = "VOID Configuration";
 		}
 
@@ -71,12 +63,13 @@
 			this.core.DrawConfigurables();
 
 			GUILayout.EndVertical();
-			GUI.DragWindow();
+
+			base.ModuleWindow(id);
 		}
 
 		~VOID_ConfigWindow()
 		{
-			VOID_ConfigWindow.Instance = null;
+			this.Dispose();
 		}
 	}
 }

--- a/VOID_Data.cs
+++ b/VOID_Data.cs
@@ -269,22 +269,22 @@
 						return double.NaN;
 					}
 
+					return Core.LastStage.totalResourceMass;
+				},
+				"tons"
+			);
+
+		public static readonly VOID_DoubleValue stageResourceMass =
+			new VOID_DoubleValue(
+				"Resource Mass (Stage)",
+				delegate()
+				{
+					if (Core.LastStage == null)
+					{
+						return double.NaN;
+					}
+
 					return Core.LastStage.resourceMass;
-				},
-				"tons"
-			);
-
-		public static readonly VOID_DoubleValue stageResourceMass =
-			new VOID_DoubleValue(
-				"Resource Mass (Stage)",
-				delegate()
-				{
-					if (Core.LastStage == null)
-					{
-						return double.NaN;
-					}
-
-					return Core.LastStage.totalResourceMass;
 				},
 				"tons"
 			);
@@ -692,22 +692,25 @@
 					double vesselLongitude = Core.Vessel.longitude * Math.PI / 180d;
 					double vesselLatitude = Core.Vessel.latitude * Math.PI / 180d;
 
-					double diffLon = vesselLongitude - kscLongitude;
-					double diffLat = vesselLatitude - kscLatitude;
-
-					double sinHalfDiffLat = Math.Sin(diffLat / 2d);
-					double sinHalfDiffLon = Math.Sin(diffLon / 2d);
-
-					double cosVesselLon = Math.Cos(vesselLongitude);
-					double cosKSCLon = Math.Cos(kscLongitude);
-
-					double haversine =
-						sinHalfDiffLat * sinHalfDiffLat +
-						cosVesselLon * cosKSCLon * sinHalfDiffLon * sinHalfDiffLon;
-
-					double arc = 2d * Math.Atan2(Math.Sqrt(haversine), Math.Sqrt(1d - haversine));
-
-					return Core.Vessel.mainBody.Radius * arc;
+					double diffLon = Math.Abs(vesselLongitude - kscLongitude);
+
+					double cosVesselLatitude = Math.Cos(vesselLatitude);
+					double sinDiffLon = Math.Sin(diffLon);
+
+					double term1 = cosVesselLatitude * sinDiffLon;
+
+					double cosKSCLatitude = Math.Cos(kscLatitude);
+					double sinVesselLatitude = Math.Sin(vesselLatitude);
+					double sinKSCLatitude = Math.Sin(kscLatitude);
+					double cosDiffLon = Math.Cos(diffLon);
+
+					double term2 = cosKSCLatitude * sinVesselLatitude - sinKSCLatitude * cosVesselLatitude * cosDiffLon;
+
+					double term3 = sinKSCLatitude * sinVesselLatitude + cosKSCLatitude * cosVesselLatitude * cosDiffLon;
+
+					double arc = Math.Atan2(Math.Sqrt(term1 * term1 + term2 * term2), term3);
+
+					return arc * Core.Vessel.mainBody.Radius;
 				},
 				"m"
 			);

--- a/VOID_SurfAtmo.cs
+++ b/VOID_SurfAtmo.cs
@@ -41,7 +41,7 @@
 
 		public VOID_SurfAtmo()
 		{
-			this.Name = "Surface & Atmospheric Information";
+			this.Name = "Surface & Atmospheric Info";
 
 			this.WindowPos.x = Screen.width - 260f;
 			this.WindowPos.y = 85;

--- a/VOID_VesselInfo.cs
+++ b/VOID_VesselInfo.cs
@@ -66,9 +66,9 @@
 
 			VOID_Data.totalMass.DoGUIHorizontal ("F3");
 
-			VOID_Data.stageResourceMass.DoGUIHorizontal("F2");
+			VOID_Data.stageResourceMass.DoGUIHorizontal("F3");
 
-			VOID_Data.resourceMass.DoGUIHorizontal("F2");
+			VOID_Data.resourceMass.DoGUIHorizontal("F3");
 
 			VOID_Data.stageDeltaV.DoGUIHorizontal (3, false);