VOID_DataValue: Changed VOID_NumValue<T> to make proper use of generic type constraints. Moved refresh timing responsibility to VOID_DataValue<T>.
VOID_DataValue: Changed VOID_NumValue<T> to make proper use of generic type constraints. Moved refresh timing responsibility to VOID_DataValue<T>.

--- a/VOID_CBInfoBrowser.cs
+++ b/VOID_CBInfoBrowser.cs
@@ -287,7 +287,7 @@
 			{
 				if (v.mainBody == body && v.situation.ToString() == "ORBITING") num_art_sats++;
 			}
-				
+
 			GUILayout.Label(num_art_sats.ToString(), VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
 
 			double g_ASL = (VOID_Core.Constant_G * body.Mass) / Math.Pow(body.Radius, 2);
@@ -303,17 +303,16 @@
 				string O2 = "No";
 				if (body.atmosphereContainsOxygen == true) O2 = "Yes";
 				GUILayout.Label(O2, VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
-
-				string ocean = "No";
-				if (body.ocean == true) ocean = "Yes";
-				GUILayout.Label(ocean, VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
 			}
 			else
 			{
 				GUILayout.Label("N/A", VOID_Core.Instance.LabelStyles["right"], 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";
+			if (body.ocean == true) ocean = "Yes";
+			GUILayout.Label(ocean, VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
 		}
 	}
 }

--- a/VOID_Core.cs
+++ b/VOID_Core.cs
@@ -849,18 +849,11 @@
 
 		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.SetIconTexture(this.powerState | this.activeState);
 
-			if (this is VOID_EditorCore)
-			{
-				this.ToolbarButton.Visibility = new GameScenesVisibility(GameScenes.EDITOR);
-			}
-			else
-			{
-				this.ToolbarButton.Visibility = new GameScenesVisibility(GameScenes.FLIGHT);
-			}
+			this.ToolbarButton.Visibility = new GameScenesVisibility(GameScenes.EDITOR, GameScenes.FLIGHT, GameScenes.SPH);
 
 			this.ToolbarButton.OnClick += 
 				(e) =>

--- a/VOID_DataValue.cs
+++ b/VOID_DataValue.cs
@@ -48,6 +48,7 @@
 		 * */
 		protected T cache;
 		protected Func<T> ValueFunc;
+		protected float lastUpdate;
 
 		/* 
 		 * Properties
@@ -55,8 +56,17 @@
 		public string Label { get; protected set; }
 		public string Units { get; protected set; }
 
-		public T Value {
-			get {
+		public T Value
+		{
+			get
+			{
+				if (
+					(VOID_Core.Instance.updateTimer - this.lastUpdate > VOID_Core.Instance.updatePeriod) ||
+					(this.lastUpdate > VOID_Core.Instance.updateTimer)
+				)
+				{
+					this.Refresh();
+				}
 				return (T)this.cache;
 			}
 		}
@@ -69,11 +79,13 @@
 			this.Label = Label;
 			this.Units = Units;
 			this.ValueFunc = ValueFunc;
+			this.lastUpdate = 0;
 		}
 
 		public void Refresh()
 		{
 			this.cache = this.ValueFunc.Invoke ();
+			this.lastUpdate = VOID_Core.Instance.updateTimer;
 		}
 
 		public T GetFreshValue()
@@ -106,30 +118,94 @@
 		}
 	}
 
-	internal interface IVOID_NumericValue
-	{
-		double ToDouble();
-		string ToString(string format);
-		string ToSIString(int digits, int MinMagnitude, int MaxMagnitude);
-	}
-
-	public abstract class VOID_NumValue<T> : VOID_DataValue<T>, IVOID_NumericValue
-	{
-		public VOID_NumValue(string Label, Func<T> ValueFunc, string Units = "") : base(Label, ValueFunc, Units) {}
-
-		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 abstract string ValueUnitString(string format);
+	public abstract class VOID_NumValue<T> : VOID_DataValue<T>
+		where T : IFormattable, IConvertible, IComparable
+	{
+		public static implicit operator Double(VOID_NumValue<T> v)
+		{
+			return v.ToDouble();
+		}
+
+		public static implicit operator Int32(VOID_NumValue<T> v)
+		{
+			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)
+		{
+			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) {
-			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)
 		{
-			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)
@@ -162,7 +238,7 @@
 			float magnitude;
 			float magLimit;
 
-			magnitude = (float)Math.Log10(Math.Abs(this.ToDouble()));
+			magnitude = (float)Math.Log10(Math.Abs(this));
 
 			magLimit = Mathf.Max(magnitude, 6f);
 			magLimit = Mathf.Round((float)Math.Ceiling(magLimit / 3f) * 3f);
@@ -198,103 +274,19 @@
 		}
 	}
 
-	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 override double ToDouble ()
-		{
-			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 class VOID_FloatValue : VOID_NumValue<float>
 	{
 		public VOID_FloatValue(string Label, Func<float> 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_IntValue : VOID_NumValue<int>, IVOID_NumericValue
+	}
+
+	public class VOID_IntValue : VOID_NumValue<int>
 	{
 		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>
 	{

--- a/VOID_Transfer.cs
+++ b/VOID_Transfer.cs
@@ -21,6 +21,7 @@
 using KSP;
 using System;
 using System.Collections.Generic;
+using System.Linq;
 using UnityEngine;
 
 namespace VOID