Got the close button working; now converting from a cached anonymous method to an inherited method. TODO: VOID_ConfigModule.
Got the close button working; now converting from a cached anonymous method to an inherited method. TODO: VOID_ConfigModule.

--- /dev/null
+++ b/API/Attributes/VOID_GameModesAttribute.cs
@@ -1,1 +1,48 @@
+// VOID
+//
+// VOID_ScenesAttribute.cs
+//
+// Copyright © 2015, toadicus
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+//    this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation and/or other
+//    materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its contributors may be used
+//    to endorse or promote products derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+using System;
 
+namespace VOID
+{
+	[AttributeUsage(AttributeTargets.Class)]
+	public class VOID_ScenesAttribute : Attribute
+	{
+		public GameScenes[] ValidScenes
+		{
+			get;
+			private set;
+		}
+
+		public VOID_ScenesAttribute(params GameScenes[] validScenes)
+		{
+			this.ValidScenes = validScenes;
+		}
+	}
+}
+
+

--- a/API/Attributes/VOID_ScenesAttribute.cs
+++ b/API/Attributes/VOID_ScenesAttribute.cs
@@ -30,17 +30,17 @@
 namespace VOID
 {
 	[AttributeUsage(AttributeTargets.Class)]
-	public class VOID_ScenesAttribute : Attribute
+	public class VOID_GameModesAttribute : Attribute
 	{
-		public GameScenes[] ValidScenes
+		public Game.Modes[] ValidModes
 		{
 			get;
 			private set;
 		}
 
-		public VOID_ScenesAttribute(params GameScenes[] validScenes)
+		public VOID_GameModesAttribute(params Game.Modes[] validModes)
 		{
-			this.ValidScenes = validScenes;
+			this.ValidModes = validModes;
 		}
 	}
 }

--- a/API/IVOID_Module.cs
+++ b/API/IVOID_Module.cs
@@ -36,6 +36,7 @@
 		bool toggleActive { get; set; }
 		bool guiRunning { get; }
 		bool inValidScene { get; }
+		bool inValidGame { get; }
 
 		void DrawGUI();
 		void StartGUI();

--- a/API/VOIDCore.cs
+++ b/API/VOIDCore.cs
@@ -35,12 +35,10 @@
 
 namespace VOID
 {
-	public abstract class VOIDCore : VOID_Module, IVOID_Module
+	public abstract class VOIDCore : VOID_WindowModule, IVOID_Module
 	{
 		public const double Constant_G = 6.674e-11;
 		public const int CONFIG_VERSION = 2;
-
-		public static bool useToolbarManager;
 
 		public abstract int configVersion { get; }
 		public virtual bool configNeedsUpdate { get; set; }
@@ -67,23 +65,14 @@
 		public abstract Stage LastStage { get; protected set; }
 		public abstract Stage[] Stages { get; protected set; }
 
-		public virtual event VOIDEventHandler onApplicationQuit;
+		public abstract event VOIDEventHandler onApplicationQuit;
+		public abstract event VOIDEventHandler onSkinChanged;
 
 		public virtual void OnGUI() {}
-
-		public virtual void OnApplicationQuit()
-		{
-			if (this.onApplicationQuit != null)
-			{
-				this.onApplicationQuit(this);
-			}
-		}
 
 		public override void LoadConfig()
 		{
 			var config = KSP.IO.PluginConfiguration.CreateForType<VOIDCore>(null);
-
-			useToolbarManager = config.GetValue("UseToolbarManager", useToolbarManager);
 
 			base.LoadConfig();
 		}
@@ -92,8 +81,6 @@
 
 		public override void _SaveToConfig(KSP.IO.PluginConfiguration config)
 		{
-			config.SetValue("UseToolbarManager", useToolbarManager);
-
 			base._SaveToConfig(config);
 		}
 	}

--- a/API/VOID_HUDModule.cs
+++ b/API/VOID_HUDModule.cs
@@ -133,9 +133,7 @@
 				}
 			}
 
-			this.positionsLocked = GUILayout.Toggle(this.positionsLocked,
-				string.Intern("Lock HUD Positions"),
-				GUILayout.ExpandWidth(false));
+			this.positionsLocked = GUITools.Toggle(this.positionsLocked, "Lock HUD Positions");
 		}
 
 		public override void LoadConfig()

--- a/API/VOID_Module.cs
+++ b/API/VOID_Module.cs
@@ -43,6 +43,7 @@
 		[AVOID_SaveValue("Active")]
 		protected VOID_SaveValue<bool> _Active = false;
 		private GameScenes[] validScenes;
+		private Game.Modes[] validModes;
 
 		protected float lastUpdate = 0;
 
@@ -57,15 +58,26 @@
 			}
 		}
 
+		protected virtual bool timeToUpdate
+		{
+			get
+			{
+				return (
+					(this.core.updateTimer - this.lastUpdate) > this.core.updatePeriod ||
+					this.lastUpdate > this.core.updateTimer
+				);
+			}
+		}
+
 		public virtual bool toggleActive
 		{
 			get
 			{
-				return this._Active;
+				return this._Active && this.inValidGame && this.inValidScene;
 			}
 			set
 			{
-				this._Active.value = value;
+				this._Active = value && this.inValidGame && this.inValidScene;
 			}
 		}
 
@@ -130,16 +142,55 @@
 		{
 			get
 			{
-
-				Tools.PostDebugMessage(
-					this,
-					"Checking if scene is valid: LoadedScene={0}, ValidScenes={1}, inValidScene={2}",
-					Enum.GetName(typeof(GameScenes), HighLogic.LoadedScene),
-					string.Join(", ", this.ValidScenes.Select(s => Enum.GetName(typeof(GameScenes), s)).ToArray()),
-					this.ValidScenes.Contains(HighLogic.LoadedScene)
-				);
-
 				return this.ValidScenes.Contains(HighLogic.LoadedScene);
+			}
+		}
+
+		public virtual Game.Modes[] ValidModes
+		{
+			get
+			{
+				if (this.validModes == null)
+				{
+					Tools.PostDebugMessage(this, "validModes is null when checking inValidGame; fetching attribute.");
+					foreach (var attr in this.GetType().GetCustomAttributes(false))
+					{
+						if (attr is VOID_GameModesAttribute)
+						{
+							VOID_GameModesAttribute addonAttr = (VOID_GameModesAttribute)attr;
+
+							this.validModes = addonAttr.ValidModes;
+
+							Tools.PostDebugMessage("Found VOID_GameModesAttribute; validScenes set.");
+
+							break;
+						}
+					}
+
+					if (this.validModes == null)
+					{
+						this.validModes = new Game.Modes[]
+						{
+							Game.Modes.CAREER,
+							Game.Modes.SANDBOX,
+							Game.Modes.SCENARIO,
+							Game.Modes.SCENARIO_NON_RESUMABLE,
+							Game.Modes.SCIENCE_SANDBOX
+						};
+
+						Tools.PostDebugMessage("No VOID_GameModesAttribute found; validScenes defaulted to flight.");
+					}
+				}
+
+				return this.validModes;
+			}
+		}
+
+		public virtual bool inValidGame
+		{
+			get
+			{
+				return this.ValidModes.Contains(HighLogic.CurrentGame.Mode);
 			}
 		}
 
@@ -361,6 +412,8 @@
 		protected float defWidth;
 		protected float defHeight;
 
+		protected bool decorateWindow;
+
 		protected string inputLockName;
 
 		public VOID_WindowModule() : base()
@@ -368,12 +421,44 @@
 			this.defWidth = 250f;
 			this.defHeight = 50f;
 
+			this.decorateWindow = true;
+
 			this.inputLockName = string.Concat(this.Name, "_edlock");
 
 			this.WindowPos = new Rect(Screen.width / 2, Screen.height / 2, this.defWidth, this.defHeight);
 		}
 
-		public abstract void ModuleWindow(int _);
+		public virtual void ModuleWindow(int id)
+		{
+			GUIStyle buttonStyle = this.core.Skin.button;
+			RectOffset padding = buttonStyle.padding;
+			RectOffset border = buttonStyle.border;
+
+			Rect closeRect = new Rect(
+				0f,
+				0f,
+				border.left + border.right,
+				border.top + border.bottom
+			);
+
+			closeRect.width = Mathf.Max(closeRect.width, 16f);
+			closeRect.height = Mathf.Max(closeRect.height, 16f);
+
+			closeRect.x = this.WindowPos.width - closeRect.width - 2f;
+			closeRect.y = 2f;
+
+			GUI.Button(closeRect, GUIContent.none, buttonStyle);
+
+			if (Event.current.type == EventType.repaint && Input.GetMouseButtonUp(0))
+			{
+				if (closeRect.Contains(Event.current.mousePosition))
+				{
+					this.toggleActive = false;
+				}
+			}
+
+			GUI.DragWindow();
+		}
 
 		public override void DrawGUI()
 		{

--- a/Tools/VOID_DataValue.cs
+++ b/Tools/VOID_DataValue.cs
@@ -145,9 +145,11 @@
 		}
 	}
 
-	public abstract class VOID_NumValue<T> : VOID_DataValue<T>
+	public abstract class VOID_NumValue<T> : VOID_DataValue<T>, IFormattable
 		where T : IFormattable, IConvertible, IComparable
 	{
+		public static IFormatProvider formatProvider = Tools.SIFormatter;
+
 		public static implicit operator Double(VOID_NumValue<T> v)
 		{
 			return v.ToDouble();
@@ -158,17 +160,14 @@
 			return v.ToInt32();
 		}
 
-
 		public static implicit operator Single(VOID_NumValue<T> v)
 		{
 			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)
@@ -178,7 +177,7 @@
 
 		public virtual double ToDouble()
 		{
-			return this.ToDouble(this.formatProvider);
+			return this.ToDouble(formatProvider);
 		}
 
 		public virtual int ToInt32(IFormatProvider provider)
@@ -188,7 +187,7 @@
 
 		public virtual int ToInt32()
 		{
-			return this.ToInt32(this.formatProvider);
+			return this.ToInt32(formatProvider);
 		}
 
 		public virtual float ToSingle(IFormatProvider provider)
@@ -198,15 +197,19 @@
 
 		public virtual float ToSingle()
 		{
-			return this.ToSingle(this.formatProvider);
-		}
-
-		public virtual string ToString(string Format)
+			return this.ToSingle(formatProvider);
+		}
+
+		public virtual string ToString(string format)
+		{
+			return this.ToString(format, formatProvider);
+		}
+
+		public virtual string ToString(string format, IFormatProvider provider)
 		{
 			return string.Format (
-				"{0}: {1}{2}",
-				this.Label,
-				this.Value.ToString(Format, this.formatProvider),
+				"{0}{1}",
+				this.Value.ToString(format, provider),
 				this.Units
 			);
 		}
@@ -222,7 +225,7 @@
 
 		public virtual string ValueUnitString(string format)
 		{
-			return this.Value.ToString(format, this.formatProvider) + this.Units;
+			return this.Value.ToString(format, formatProvider) + this.Units;
 		}
 		
 		public virtual string ValueUnitString(int digits) {

--- a/Tools/VOID_Tools.cs
+++ b/Tools/VOID_Tools.cs
@@ -34,7 +34,7 @@
 
 namespace VOID
 {
-	public static partial class VOID_Tools
+	public static class VOID_Tools
 	{
 		#region CelestialBody Utilities
 		public static bool hasAncestor(this CelestialBody bodyA, CelestialBody bodyB)
@@ -365,6 +365,19 @@
 			return functionCache[hashCode];
 		}
 
+		public static void UncacheWindow(Action<int> func)
+		{
+			if (functionCache != null)
+			{
+				int hashCode = func.GetHashCode();
+
+				if (functionCache.ContainsKey(hashCode))
+				{
+					functionCache.Remove(hashCode);
+				}
+			}
+		}
+
 		/// <summary>
 		/// Formats the interval given in seconds as a human-friendly
 		/// time period in [[[[years, ]days, ]hours, ]minutes, and ]seconds.
@@ -518,7 +531,7 @@
 			{
 				string format = "Y{0:#0}, D{1:#0} {2:00}:{3:00}:{4:00.0}s";
 
-				return string.Format(format, years + 1, days, hours, minutes, seconds);
+				return string.Format(format, years + 1, days + 1, hours, minutes, seconds);
 			}
 
 			public UnpackedTime(int years, int days, int hours, int minutes, double seconds)

--- a/VOID.csproj
+++ b/VOID.csproj
@@ -111,6 +111,8 @@
     <Compile Include="API\Attributes\VOID_ScenesAttribute.cs" />
     <Compile Include="API\Attributes\AVOID_SaveValue.cs" />
     <Compile Include="API\VOIDMaster.cs" />
+    <Compile Include="API\Attributes\VOID_GameModesAttribute.cs" />
+    <Compile Include="VOID_ConfigModule.cs" />
   </ItemGroup>
   <ProjectExtensions>
     <MonoDevelop>

--- a/VOIDCore_Editor.cs
+++ b/VOIDCore_Editor.cs
@@ -36,6 +36,7 @@
 
 namespace VOID
 {
+	[VOID_Scenes(GameScenes.EDITOR)]
 	public class VOIDCore_Editor : VOIDCore_Generic<VOIDCore_Editor>
 	{
 		public VOIDCore_Editor() : base()

--- a/VOIDCore_Flight.cs
+++ b/VOIDCore_Flight.cs
@@ -29,9 +29,11 @@
 using KSP;
 using System;
 using UnityEngine;
+using ToadicusTools;
 
 namespace VOID
 {
+	[VOID_Scenes(GameScenes.FLIGHT)]
 	public class VOIDCore_Flight : VOIDCore_Generic<VOIDCore_Flight>
 	{
 		public VOIDCore_Flight()
@@ -43,7 +45,7 @@
 		{
 			if (HighLogic.LoadedSceneIsFlight)
 			{
-				this.consumeResource.value = GUILayout.Toggle(this.consumeResource, "Consume Resources");
+				this.consumeResource.value = GUITools.Toggle(this.consumeResource, "Consume Resources");
 			}
 
 			base.DrawConfigurables();

--- a/VOIDCore_Generic.cs
+++ b/VOIDCore_Generic.cs
@@ -118,6 +118,8 @@
 				"SSUITextAreaDefault",
 				"ExperimentsDialogSkin",
 				"ExpRecoveryDialogSkin",
+				"KSP window 1",
+				"KSP window 3",
 				"KSP window 5",
 				"KSP window 6",
 				"PartTooltipSkin",
@@ -284,6 +286,8 @@
 			}
 		}
 
+		private bool useToolbarManager;
+
 		protected bool UseToolbarManager
 		{
 			get
@@ -324,6 +328,12 @@
 				return HighLogic.LoadedScene.ToAppScenes();
 			}
 		}
+
+		/*
+		 * Events
+		 * */
+		public override event VOIDEventHandler onApplicationQuit;
+		public override event VOIDEventHandler onSkinChanged;
 
 		/*
 		 * Methods
@@ -377,6 +387,8 @@
 				this.InitializeToolbarButton();
 			}
 
+			base.DrawGUI();
+/*
 			if (!this.mainGuiMinimized)
 			{
 
@@ -385,10 +397,17 @@
 				_mainWindowPos = GUILayout.Window(
 					this.windowID,
 					_mainWindowPos,
-					VOID_Tools.GetWindowHandler(this.VOIDMainWindow),
+					VOID_Tools.GetWindowHandler(
+						VOID_WindowModule.DecorateWindow(
+							this.VOIDMainWindow,
+							_mainWindowPos,
+							(bool active) => { this.mainGuiMinimized = !active; }
+						)),
 					string.Join(" ", new string[] { this.VoidName, this.VoidVersion }),
-					GUILayout.Width(250),
-					GUILayout.Height(50)
+					GUILayout.Width(250f),
+					GUILayout.Height(50f),
+					GUILayout.ExpandWidth(true),
+					GUILayout.ExpandHeight(true)
 				);
 
 				if (HighLogic.LoadedSceneIsEditor)
@@ -413,7 +432,11 @@
 				_configWindowPos = GUILayout.Window(
 					this.windowID,
 					_configWindowPos,
-					VOID_Tools.GetWindowHandler(this.VOIDConfigWindow),
+					VOID_Tools.GetWindowHandler(VOID_WindowModule.DecorateWindow(
+						this.VOIDConfigWindow,
+						_configWindowPos,
+						(bool active) => { this.configWindowMinimized = !active; }
+					)),
 					string.Join(" ", new string[] { this.VoidName, "Configuration" }),
 					GUILayout.Width(250),
 					GUILayout.Height(50)
@@ -432,7 +455,7 @@
 				{
 					this.configWindowPos = _configWindowPos;
 				}
-			}
+			}*/
 		}
 
 		public virtual void Update()
@@ -462,27 +485,6 @@
 
 			foreach (IVOID_Module module in this.Modules)
 			{
-				Tools.PostDebugMessage(
-					this,
-					"\n\tmodule.Name={0}" +
-					"\n\tmodule.guiRunning={1}" +
-					"\n\tmodule.toggleActive={2}" +
-					"\n\tmodule.inValidScene={3}" +
-					"\n\tthis.togglePower={4}" +
-					"\n\tthis.factoryReset={5}" +
-					"\n\tHighLogic.LoadedSceneIsEditor={6}" +
-					"\n\t(EditorLogic.RootPart != null && EditorLogic.SortedShipList.Count > 0)={7}" +
-					"\n\t(EditorLogic.RootPart == null || EditorLogic.SortedShipList.Count == 0)={8}",
-					module.Name,
-					module.guiRunning,
-					module.toggleActive,
-					module.inValidScene,
-					this.togglePower,
-					this.factoryReset,
-					HighLogic.LoadedSceneIsEditor,
-					(EditorLogic.RootPart != null && EditorLogic.SortedShipList.Count > 0),
-					(EditorLogic.RootPart == null || EditorLogic.SortedShipList.Count == 0)
-				);
 				if (
 					!module.guiRunning &&
 					module.toggleActive &&
@@ -573,6 +575,16 @@
 			this.Dispose();
 		}
 
+		public virtual void OnApplicationQuit()
+		{
+			if (this.onApplicationQuit != null)
+			{
+				this.onApplicationQuit(this);
+			}
+
+			this.OnDestroy();
+		}
+
 		public void ResetGUI()
 		{
 			this.StopGUI();
@@ -586,7 +598,7 @@
 			this.StartGUI();
 		}
 
-		public void VOIDMainWindow(int _)
+		public override void ModuleWindow(int id)
 		{
 			GUILayout.BeginVertical();
 
@@ -608,7 +620,7 @@
 				{
 					foreach (IVOID_Module module in this.Modules)
 					{
-						module.toggleActive = GUILayout.Toggle(module.toggleActive, module.Name);
+						module.toggleActive = GUITools.Toggle(module.toggleActive, module.Name);
 					}
 				}
 			}
@@ -617,29 +629,30 @@
 				GUILayout.Label("-- POWER LOST --", VOID_Styles.labelRed);
 			}
 
-			this.configWindowMinimized.value = !GUILayout.Toggle(!this.configWindowMinimized, "Configuration");
+			this.configWindowMinimized.value = !GUITools.Toggle(!this.configWindowMinimized, "Configuration");
+
+			GUILayout.EndVertical();
+
+			base.ModuleWindow(id);
+		}
+
+		public void VOIDConfigWindow(int _)
+		{
+			GUILayout.BeginVertical();
+
+			this.DrawConfigurables();
 
 			GUILayout.EndVertical();
 			GUI.DragWindow();
 		}
 
-		public void VOIDConfigWindow(int _)
-		{
-			GUILayout.BeginVertical();
-
-			this.DrawConfigurables();
-
-			GUILayout.EndVertical();
-			GUI.DragWindow();
-		}
-
 		public override void DrawConfigurables()
 		{
 			GUIContent _content;
 
-			this.UseToolbarManager = GUILayout.Toggle(this.UseToolbarManager, "Use Blizzy's Toolbar If Available");
-
-			this.vesselSimActive.value = GUILayout.Toggle(this.vesselSimActive.value,
+			this.UseToolbarManager = GUITools.Toggle(this.UseToolbarManager, "Use Blizzy's Toolbar If Available");
+
+			this.vesselSimActive.value = GUITools.Toggle(this.vesselSimActive.value,
 				"Enable Engineering Calculations");
 
 			GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
@@ -713,22 +726,13 @@
 				mod.DrawConfigurables();
 			}
 
-			this.factoryReset = GUILayout.Toggle(this.factoryReset, "Factory Reset");
+			this.factoryReset = GUITools.Toggle(this.factoryReset, "Factory Reset");
 		}
 
 		protected void UpdateSimManager()
 		{
 			if (SimManager.ResultsReady())
 			{
-				Tools.PostDebugMessage(this, "VesselSimulator results ready, setting Stages.");
-
-				this.Stages = SimManager.Stages;
-
-				if (this.Stages != null)
-				{
-					this.LastStage = this.Stages.Last();
-				}
-
 				if (HighLogic.LoadedSceneIsEditor)
 				{
 					SimManager.Gravity = VOID_Data.KerbinGee;
@@ -749,6 +753,18 @@
 				Tools.PostDebugMessage(this, "VesselSimulator results not ready.");
 			}
 			#endif
+		}
+
+		protected void GetSimManagerResults()
+		{
+			Tools.PostDebugMessage(this, "VesselSimulator results ready, setting Stages.");
+
+			this.Stages = SimManager.Stages;
+
+			if (this.Stages != null)
+			{
+				this.LastStage = this.Stages.Last();
+			}
 		}
 
 		protected void LoadModulesOfType<U>()
@@ -941,6 +957,11 @@
 		protected void LoadGUIStyles()
 		{
 			VOID_Styles.OnSkinChanged();
+
+			if (this.onSkinChanged != null)
+			{
+				this.onSkinChanged(this);
+			}
 
 			this.GUIStylesLoaded = true;
 		}
@@ -1135,6 +1156,8 @@
 			this.updateTimer = 0f;
 
 			this.vesselSimActive = true;
+			SimManager.Atmosphere = 0d;
+			SimManager.OnReady += this.GetSimManagerResults;
 
 			this.UseToolbarManager = ToolbarManager.ToolbarAvailable;
 
@@ -1150,6 +1173,8 @@
 		public virtual void Dispose()
 		{
 			this.StopGUI();
+
+			this.onSkinChanged(this);
 
 			if (this.AppLauncherButton != null)
 			{

--- a/VOIDCore_SpaceCentre.cs
+++ b/VOIDCore_SpaceCentre.cs
@@ -29,6 +29,7 @@
 
 namespace VOID
 {
+	[VOID_Scenes(GameScenes.SPACECENTER)]
 	public class VOIDCore_SpaceCentre : VOIDCore_Generic<VOIDCore_SpaceCentre>
 	{
 		public VOIDCore_SpaceCentre() : base()

--- a/VOID_CBInfoBrowser.cs
+++ b/VOID_CBInfoBrowser.cs
@@ -62,7 +62,7 @@
 			this.WindowPos.y = 85;
 		}
 
-		public override void ModuleWindow(int _)
+		public override void ModuleWindow(int id)
 		{
 			GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
 
@@ -277,7 +277,7 @@
 				GUILayout.EndHorizontal();
 			}
 
-			GUI.DragWindow();
+			base.ModuleWindow(id);
 		}
 
 		private void body_OP_show_orbital_info(CelestialBody body)

--- a/VOID_CareerStatus.cs
+++ b/VOID_CareerStatus.cs
@@ -35,6 +35,7 @@
 namespace VOID
 {
 	[VOID_Scenes(GameScenes.FLIGHT, GameScenes.EDITOR, GameScenes.SPACECENTER)]
+	[VOID_GameModes(Game.Modes.CAREER, Game.Modes.SCIENCE_SANDBOX)]
 	public class VOID_CareerStatus : VOID_WindowModule
 	{
 		public static VOID_CareerStatus Instance
@@ -43,20 +44,25 @@
 			private set;
 		}
 
+		public static string formatDelta(double delta, string numberFormat)
+		{
+			if (delta > 0)
+			{
+				return string.Format("<color='lime'>{0}↑</color>", delta.ToString(numberFormat, Tools.SIFormatter));
+			}
+			else if (delta < 0)
+			{
+				return string.Format("<color='red'>{0}↓</color>", delta.ToString(numberFormat, Tools.SIFormatter));
+			}
+			else
+			{
+				return "0";
+			}
+		}
+
 		public static string formatDelta(double delta)
 		{
-			if (delta > 0)
-			{
-				return string.Format("<color='green'>{0:#,#.##}↑</color>", delta);
-			}
-			else if (delta < 0)
-			{
-				return string.Format("<color='red'>{0:#,#.##}↓</color>", delta);
-			}
-			else
-			{
-				return string.Intern("0");
-			}
+			return formatDelta(delta, "#,##0.##");
 		}
 
 		public static string formatDelta(float delta)
@@ -76,18 +82,6 @@
 		private Texture2D scienceIcon;
 		#pragma warning restore 0414
 
-		public override bool toggleActive
-		{
-			get
-			{
-				return base.toggleActive && this.inValidGame;
-			}
-			set
-			{
-				base.toggleActive = this.inValidGame && value;
-			}
-		}
-
 		public double lastFundsChange
 		{
 			get;
@@ -122,21 +116,6 @@
 		{
 			get;
 			private set;
-		}
-
-		private bool inValidGame
-		{
-			get
-			{
-				switch (HighLogic.CurrentGame.Mode)
-				{
-					case Game.Modes.CAREER:
-					case Game.Modes.SCIENCE_SANDBOX:
-						return true;
-					default:
-						return false;
-				}
-			}
 		}
 
 		private bool currenciesInitialized
@@ -172,7 +151,7 @@
 			base.DrawGUI();
 		}
 
-		public override void ModuleWindow(int _)
+		public override void ModuleWindow(int id)
 		{
 			GUILayout.BeginVertical();
 
@@ -199,7 +178,7 @@
 
 			GUILayout.EndVertical();
 
-			GUI.DragWindow();
+			base.ModuleWindow(id);
 		}
 
 		// TODO: Update event handlers to do something useful with the new "reasons" parameter.
@@ -219,6 +198,11 @@
 		{
 			this.lastScienceChange = newValue - this.currentScience;
 			this.currentScience = newValue;
+		}
+
+		private void onGameStateLoad(ConfigNode node)
+		{
+			this.initCurrencies();
 		}
 
 		private void initCurrencies()
@@ -256,6 +240,7 @@
 			GameEvents.OnFundsChanged.Add(this.onFundsChange);
 			GameEvents.OnReputationChanged.Add(this.onRepChange);
 			GameEvents.OnScienceChanged.Add(this.onScienceChange);
+			GameEvents.onGameStateLoad.Add(this.onGameStateLoad);
 
 			bool texturesLoaded;
 
@@ -286,6 +271,7 @@
 			GameEvents.OnFundsChanged.Remove(this.onFundsChange);
 			GameEvents.OnReputationChanged.Remove(this.onRepChange);
 			GameEvents.OnScienceChanged.Remove(this.onScienceChange);
+			GameEvents.onGameStateLoad.Remove(this.onGameStateLoad);
 
 			VOID_CareerStatus.Instance = null;
 		}

--- a/VOID_Data.cs
+++ b/VOID_Data.cs
@@ -283,7 +283,7 @@
 						return double.NaN;
 					}
 
-					return Core.LastStage.resourceMass;
+					return Core.LastStage.totalResourceMass;
 				},
 				"tons"
 			);
@@ -1150,6 +1150,50 @@
 				"°"
 			);
 
+		public static readonly VOID_StrValue timeToAscendingNode =
+			new VOID_StrValue(
+				"Time to Ascending Node",
+				delegate()
+				{
+					double trueAnomalyAscNode = 360d - argumentPeriapsis;
+					double dTAscNode = Core.vessel.orbit.GetDTforTrueAnomaly(
+						trueAnomalyAscNode * Mathf.Deg2Rad,
+						Core.vessel.orbit.period
+					);
+
+					dTAscNode %= Core.vessel.orbit.period;
+
+					if (dTAscNode < 0d)
+					{
+						dTAscNode += Core.vessel.orbit.period;
+					}
+
+					return VOID_Tools.FormatInterval(dTAscNode);
+				}
+			);
+
+		public static readonly VOID_StrValue timeToDescendingNode =
+			new VOID_StrValue(
+				"Time to Descending Node",
+				delegate()
+				{
+					double trueAnomalyAscNode = 180d - argumentPeriapsis;
+					double dTDescNode = Core.vessel.orbit.GetDTforTrueAnomaly(
+						trueAnomalyAscNode * Mathf.Deg2Rad,
+						Core.vessel.orbit.period
+					);
+
+					dTDescNode %= Core.vessel.orbit.period;
+
+					if (dTDescNode < 0d)
+					{
+						dTDescNode += Core.vessel.orbit.period;
+					}
+
+					return VOID_Tools.FormatInterval(dTDescNode);
+				}
+			);
+
 		public static readonly VOID_DoubleValue localSiderealLongitude =
 			new VOID_DoubleValue(
 				"Local Sidereal Longitude",
@@ -1171,7 +1215,17 @@
 		public static readonly VOID_StrValue currBiome =
 			new VOID_StrValue(
 				"Biome",
-				new Func<string>(() => VOID_Tools.GetBiome(Core.vessel).name)
+				delegate()
+				{
+					if (Core.vessel.landedAt == string.Empty)
+					{
+						return VOID_Tools.GetBiome(Core.vessel).name;
+					}
+					else
+					{
+						return Core.vessel.landedAt;
+					}
+				}
 			);
 
 		#endregion

--- a/VOID_DataLogger.cs
+++ b/VOID_DataLogger.cs
@@ -45,6 +45,9 @@
 
 		protected bool _loggingActive;
 		protected bool firstWrite;
+
+		[AVOID_SaveValue("waitForLaunch")]
+		protected VOID_SaveValue<bool> waitForLaunch;
 
 		[AVOID_SaveValue("logInterval")]
 		protected VOID_SaveValue<float> logInterval;
@@ -194,7 +197,7 @@
 
 			// CSV Logging
 			// from ISA MapSat
-			if (loggingActive)
+			if (loggingActive && (!waitForLaunch || this.vessel.situation != Vessel.Situations.PRELAUNCH))
 			{
 				//data logging is on
 				//increment timers
@@ -234,7 +237,7 @@
 			this.logIntervalStr = this.logInterval.value.ToString("#.0##");
 		}
 
-		public override void ModuleWindow(int _)
+		public override void ModuleWindow(int id)
 		{
 			GUILayout.BeginVertical();
 
@@ -255,12 +258,17 @@
 				activeLabelStyle = VOID_Styles.labelGreen;
 			}
 
-			GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
-
-			this.loggingActive = GUILayout.Toggle(loggingActive, "Data logging: ", GUILayout.ExpandWidth(false));
-			GUILayout.Label(activeLabelText, activeLabelStyle, GUILayout.ExpandWidth(true));
-
-			GUILayout.EndHorizontal();
+			this.loggingActive = GUITools.Toggle(
+				loggingActive,
+				string.Format("Data logging: {0}", activeLabelText),
+				null,
+				activeLabelStyle
+			);
+
+			this.waitForLaunch.value = GUITools.Toggle(
+				this.waitForLaunch,
+				"Wait for launch"
+			);
 
 			GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
 
@@ -280,7 +288,7 @@
 
 			GUILayout.EndVertical();
 
-			GUI.DragWindow();
+			base.ModuleWindow(id);
 		}
 
 		#endregion
@@ -459,6 +467,8 @@
 			this.loggingActive = false;
 			this.firstWrite = true;
 
+			this.waitForLaunch = true;
+
 			this.logInterval = 0.5f;
 			this.csvCollectTimer = 0f;
 

--- a/VOID_HUDAdvanced.cs
+++ b/VOID_HUDAdvanced.cs
@@ -265,9 +265,7 @@
 				}
 			}
 
-			this.positionsLocked = GUILayout.Toggle(this.positionsLocked,
-				string.Intern("Lock Advanced HUD Positions"),
-				GUILayout.ExpandWidth(false));
+			this.positionsLocked = GUITools.Toggle(this.positionsLocked, string.Intern("Lock Advanced HUD Positions"));
 		}
 	}
 }

--- a/VOID_Orbital.cs
+++ b/VOID_Orbital.cs
@@ -50,7 +50,7 @@
 			this.WindowPos.y = 250f;
 		}
 
-		public override void ModuleWindow(int _)
+		public override void ModuleWindow(int id)
 		{
 			int idx = 0;
 
@@ -79,7 +79,7 @@
 			this.precisionValues [idx]= (ushort)VOID_Data.gravityAccel.DoGUIHorizontal (this.precisionValues [idx]);
 			idx++;
 
-			this.toggleExtended.value = GUILayout.Toggle(this.toggleExtended, "Extended info");
+			this.toggleExtended.value = GUITools.Toggle(this.toggleExtended, "Extended info");
 
 			if (this.toggleExtended)
             {
@@ -98,13 +98,18 @@
 
 				VOID_Data.longitudeAscNode.DoGUIHorizontal("F3");
 
+				VOID_Data.timeToAscendingNode.DoGUIHorizontal();
+
+				VOID_Data.timeToDescendingNode.DoGUIHorizontal();
+
 				VOID_Data.argumentPeriapsis.DoGUIHorizontal("F3");
 
 				VOID_Data.localSiderealLongitude.DoGUIHorizontal("F3");
             }
 
             GUILayout.EndVertical();
-            GUI.DragWindow();
+            
+			base.ModuleWindow(id);
 		}
 
 		public override void LoadConfig ()

--- a/VOID_Rendezvous.cs
+++ b/VOID_Rendezvous.cs
@@ -53,7 +53,7 @@
 			this.WindowPos.y = 85;
 		}
 
-		public override void ModuleWindow(int _)
+		public override void ModuleWindow(int id)
 		{
 			Vessel rendezvessel = new Vessel();
 			CelestialBody rendezbody = new CelestialBody();
@@ -126,7 +126,7 @@
 				}
 			}
 
-			untoggleRegisterInfo.value = GUILayout.Toggle(untoggleRegisterInfo, "Hide Vessel Register Info");
+			untoggleRegisterInfo.value = GUITools.Toggle(untoggleRegisterInfo, "Hide Vessel Register Info");
 
 			GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
 			GUILayout.Label(" ", GUILayout.ExpandWidth(true));
@@ -134,7 +134,8 @@
 			GUILayout.EndHorizontal();
 
 			GUILayout.EndVertical();
-			GUI.DragWindow();
+
+			base.ModuleWindow(id);
 		}
 
 		private void display_rendezvous_info(Vessel v, CelestialBody cb)
@@ -199,7 +200,7 @@
 					GUILayout.Label(LSL.ToString("F3") + "°", VOID_Styles.labelRight);
 					GUILayout.EndHorizontal();
 
-					toggleExtendedOrbital.value = GUILayout.Toggle(toggleExtendedOrbital, "Extended info");
+					toggleExtendedOrbital.value = GUITools.Toggle(toggleExtendedOrbital, "Extended info");
 
 					if (toggleExtendedOrbital)
 					{

--- a/VOID_StageInfo.cs
+++ b/VOID_StageInfo.cs
@@ -26,60 +26,82 @@
 		private Table.Column<double> stageTotalMassCol;
 		private Table.Column<double> stageThrustCol;
 		private Table.Column<double> stageTWRCol;
+		private Table.Column<string> stageTimeCol;
 
 		private bool stylesApplied;
+
 		private bool showBodyList;
-
 		private Rect bodyListPos;
+
+		private bool showColumnSelection;
 
 		private CelestialBody selectedBody;
 		[AVOID_SaveValue("bodyIdx")]
 		private VOID_SaveValue<int> bodyIdx;
 		private int lastIdx;
 
+		private bool showAdvanced;
+
+		[AVOID_SaveValue("UseSealLevel")]
+		private VOID_SaveValue<bool> useSeaLevel;
+		private GUIContent seaLevelToggle;
+
 		public VOID_StageInfo() : base()
 		{
 			this.Name = "Stage Information";
-			this.defWidth = 200f;
+			this.defWidth = 20f;
 			this.bodyIdx = 4;
 
 			this.stylesApplied = false;
 			this.showBodyList = false;
+			this.showColumnSelection = false;
 
 			this.bodyListPos = new Rect();
 
 			this.stageTable = new Table();
 
-			this.stageNumberCol = new Table.Column<int>("Stage", 40f);
+			this.stageNumberCol = new Table.Column<int>("Stage", 20f);
 			this.stageTable.Add(this.stageNumberCol);
 
-			this.stageDeltaVCol = new Table.Column<double>("DeltaV [m/s]", 60f);
+			this.stageDeltaVCol = new Table.Column<double>("DeltaV [m/s]", 20f);
 			this.stageDeltaVCol.Format = "S2";
 			this.stageTable.Add(this.stageDeltaVCol);
 
-			this.stageTotalDVCol = new Table.Column<double>("Total ΔV [m/s]", 60f);
+			this.stageTotalDVCol = new Table.Column<double>("Total ΔV [m/s]", 20f);
 			this.stageTotalDVCol.Format = "S2";
 			this.stageTable.Add(this.stageTotalDVCol);
 
-			this.stageInvertDVCol = new Table.Column<double>("Invert ΔV [m/s]", 60f);
+			this.stageInvertDVCol = new Table.Column<double>("Invert ΔV [m/s]", 20f);
 			this.stageInvertDVCol.Format = "S2";
 			this.stageTable.Add(this.stageInvertDVCol);
 
-			this.stageMassCol = new Table.Column<double>("Mass [Mg]", 60f);
+			this.stageMassCol = new Table.Column<double>("Mass [Mg]", 20f);
 			this.stageMassCol.Format = "#.#";
 			this.stageTable.Add(this.stageMassCol);
 
-			this.stageTotalMassCol = new Table.Column<double>("Total [Mg]", 60f);
+			this.stageTotalMassCol = new Table.Column<double>("Total [Mg]", 20f);
 			this.stageTotalMassCol.Format = "#.#";
 			this.stageTable.Add(this.stageTotalMassCol);
 
-			this.stageThrustCol = new Table.Column<double>("Thrust [N]", 60f);
+			this.stageThrustCol = new Table.Column<double>("Thrust [N]", 20f);
 			this.stageThrustCol.Format = "S2";
 			this.stageTable.Add(this.stageThrustCol);
 
-			this.stageTWRCol = new Table.Column<double>("T/W Ratio", 60f);
+			this.stageTWRCol = new Table.Column<double>("T/W Ratio", 20f);
 			this.stageTWRCol.Format = "#.#";
 			this.stageTable.Add(this.stageTWRCol);
+
+			this.stageTimeCol = new Table.Column<string>("Burn Time", 20f);
+			this.stageTable.Add(this.stageTimeCol);
+
+			this.showAdvanced = false;
+
+			this.useSeaLevel = false;
+
+			seaLevelToggle = new GUIContent(
+				"Use Sea Level",
+				"Use 'sea' level atmospheric conditions on bodies with atmospheres."
+			);
 		}
 
 		public override void DrawGUI()
@@ -92,8 +114,13 @@
 			}
 		}
 
-		public override void ModuleWindow(int _)
-		{
+		public override void ModuleWindow(int id)
+		{
+			if (this.selectedBody == null)
+			{
+				this.selectedBody = core.HomeBody;
+			}
+
 			if (
 				!HighLogic.LoadedSceneIsFlight ||
 				(TimeWarp.WarpMode == TimeWarp.Modes.LOW) ||
@@ -122,6 +149,15 @@
 				return;
 			}
 
+			if (HighLogic.LoadedSceneIsEditor && this.selectedBody.atmosphere && this.useSeaLevel)
+			{
+				SimManager.Atmosphere = this.selectedBody.atmosphereMultiplier * 101.325d;
+			}
+			else
+			{
+				SimManager.Atmosphere = 0d;
+			}
+
 			foreach (Stage stage in core.Stages)
 			{
 				if (stage.deltaV == 0 && stage.mass == 0)
@@ -140,6 +176,8 @@
 
 				this.stageThrustCol.Add(stage.thrust * 1000f);
 				this.stageTWRCol.Add(stage.thrustToWeight / (this.selectedBody ?? core.HomeBody).GeeASL);
+
+				this.stageTimeCol.Add(VOID_Tools.FormatInterval(stage.time));
 			}
 
 			this.stageTable.Render();
@@ -153,7 +191,12 @@
 					this.bodyIdx--;
 				}
 
-				this.showBodyList = GUILayout.Toggle(this.showBodyList, (this.selectedBody ?? core.HomeBody).bodyName, GUI.skin.button);
+				this.showBodyList = GUILayout.Toggle(
+					this.showBodyList,
+					(this.selectedBody ?? core.HomeBody).bodyName,
+					GUI.skin.button
+				);
+
 				Rect bodyButtonPos = GUILayoutUtility.GetLastRect();
 
 				if (Event.current.type == EventType.Repaint)
@@ -180,6 +223,28 @@
 					this.lastIdx = this.bodyIdx;
 					this.selectedBody = core.sortedBodyList[this.bodyIdx];
 				}
+
+				if (HighLogic.LoadedSceneIsEditor)
+				{
+					if (
+						GUILayout.Button(
+							this.showAdvanced ? "▲" : "▼",
+							GUILayout.ExpandWidth(false)
+						)
+					)
+					{
+						this.showAdvanced = !this.showAdvanced;
+					}
+				}
+
+				GUILayout.EndHorizontal();
+			}
+
+			if (this.showAdvanced && HighLogic.LoadedSceneIsEditor)
+			{
+				GUILayout.BeginHorizontal();
+
+				this.useSeaLevel.value = GUITools.Toggle(this.useSeaLevel, this.seaLevelToggle, false);
 
 				GUILayout.EndHorizontal();
 			}
@@ -196,7 +261,16 @@
 
 			GUILayout.EndHorizontal();
 
-			GUI.DragWindow();
+			base.ModuleWindow(id);
+		}
+
+		public override void DrawConfigurables()
+		{
+			this.showColumnSelection = GUILayout.Toggle(
+				this.showColumnSelection,
+				"Select StageInfo Columns",
+				GUI.skin.button
+			);
 		}
 
 		private void BodyPickerWindow(int _)

--- a/VOID_SurfAtmo.cs
+++ b/VOID_SurfAtmo.cs
@@ -47,7 +47,7 @@
 			this.WindowPos.y = 85;
 		}
 
-		public override void ModuleWindow(int _)
+		public override void ModuleWindow(int id)
 		{
 			int idx = 0;
 
@@ -91,7 +91,8 @@
 			VOID_Data.currBiome.DoGUIHorizontal ();
 
 			GUILayout.EndVertical();
-			GUI.DragWindow();
+
+			base.ModuleWindow(id);
 		}
 
 		public override void LoadConfig ()

--- a/VOID_TWR.cs
+++ b/VOID_TWR.cs
@@ -20,7 +20,7 @@
 			this.Name = "IP Thrust-to-Weight Ratios";
 		}
 
-		public override void ModuleWindow(int _)
+		public override void ModuleWindow(int id)
 		{
 			if (
 				!HighLogic.LoadedSceneIsFlight ||
@@ -60,7 +60,7 @@
 
 			GUILayout.EndVertical();
 
-			GUI.DragWindow();
+			base.ModuleWindow(id);
 		}
 	}
 }

--- a/VOID_Transfer.cs
+++ b/VOID_Transfer.cs
@@ -48,7 +48,7 @@
 			this.defWidth = 315;
 		}
 
-		public override void ModuleWindow(int _)
+		public override void ModuleWindow(int id)
 		{
 			GUILayout.BeginVertical();
 
@@ -140,7 +140,8 @@
 				}
 			}
 			GUILayout.EndVertical();
-			GUI.DragWindow();
+
+			base.ModuleWindow(id);
 		}
 
 		private void tad_targeting(CelestialBody body)

--- a/VOID_VesselInfo.cs
+++ b/VOID_VesselInfo.cs
@@ -46,7 +46,7 @@
 			this.WindowPos.y = 450;
 		}
 
-		public override void ModuleWindow(int _)
+		public override void ModuleWindow(int id)
 		{
 			if ((TimeWarp.WarpMode == TimeWarp.Modes.LOW) || (TimeWarp.CurrentRate <= TimeWarp.MaxPhysicsRate))
 			{
@@ -86,7 +86,7 @@
 
 			GUILayout.EndVertical();
 
-			GUI.DragWindow();
+			base.ModuleWindow(id);
 		}
 	}
 }

--- a/VOID_VesselRegister.cs
+++ b/VOID_VesselRegister.cs
@@ -67,7 +67,7 @@
 			this.defHeight = 375;
 		}
 
-		public override void ModuleWindow(int _)
+		public override void ModuleWindow(int id)
 		{
 			if (!this.core.allVesselTypes.Any())
 			{
@@ -157,7 +157,7 @@
 
 			GUILayout.EndVertical();
 
-			GUI.DragWindow();
+			base.ModuleWindow(id);
 		}
 	}
 }