ARFlightController: Added toolbar button for visually tracking connection status (red/yellow/green).
ARFlightController: Added toolbar button for visually tracking connection status (red/yellow/green).

--- a/ARConfiguration.cs
+++ b/ARConfiguration.cs
@@ -7,8 +7,6 @@
 using System;
 using ToadicusTools;
 using UnityEngine;
-
-[assembly: KSPAssemblyDependency("ToadicusTools", 0, 0)]
 
 namespace AntennaRange
 {
@@ -69,6 +67,7 @@
 				AntennaRelay.requireLineOfSight = this.LoadConfigValue("requireLineOfSight", false);
 				ARFlightController.requireConnectionForControl =
 					this.LoadConfigValue("requireConnectionForControl", false);
+				ModuleLimitedDataTransmitter.fixedPowerCost = this.LoadConfigValue("fixedPowerCost", false);
 
 				Debug.Log(string.Format("{0} v{1} - ARonfiguration loaded!", this.GetType().Name, this.runningVersion));
 			}
@@ -123,6 +122,17 @@
 
 			GUILayout.EndHorizontal();
 
+			GUILayout.BeginHorizontal();
+
+			bool fixedPowerCost = GUILayout.Toggle(ModuleLimitedDataTransmitter.fixedPowerCost, "Use fixed power cost");
+			if (fixedPowerCost != ModuleLimitedDataTransmitter.fixedPowerCost)
+			{
+				ModuleLimitedDataTransmitter.fixedPowerCost = fixedPowerCost;
+				this.SaveConfigValue("fixedPowerCost", fixedPowerCost);
+			}
+
+			GUILayout.EndHorizontal();
+
 			GUILayout.EndVertical();
 
 			GUI.DragWindow();

--- a/ARFlightController.cs
+++ b/ARFlightController.cs
@@ -28,6 +28,7 @@
 
 using KSP;
 using System;
+using System.Collections.Generic;
 using ToadicusTools;
 using UnityEngine;
 
@@ -40,26 +41,46 @@
 		public static bool requireConnectionForControl;
 		#endregion
 
+		#region Fields
+		protected Dictionary<ConnectionStatus, string> connectionTextures;
+
+		protected IButton toolbarButton;
+		#endregion
+
 		#region Properties
-		public ControlTypes currentControlLock
-		{
-			get
-			{
-				if (this.lockID == string.Empty)
-				{
-					return ControlTypes.None;
-				}
-
-				return InputLockManager.GetControlLock(this.lockID);
-			}
-		}
-
-		public string lockID
+		public ConnectionStatus currentConnectionStatus
 		{
 			get;
 			protected set;
 		}
 
+		protected string currentConnectionTexture
+		{
+			get
+			{
+				return this.connectionTextures[this.currentConnectionStatus];
+			}
+		}
+
+		public ControlTypes currentControlLock
+		{
+			get
+			{
+				if (this.lockID == string.Empty)
+				{
+					return ControlTypes.None;
+				}
+
+				return InputLockManager.GetControlLock(this.lockID);
+			}
+		}
+
+		public string lockID
+		{
+			get;
+			protected set;
+		}
+
 		public ControlTypes lockSet
 		{
 			get
@@ -86,6 +107,22 @@
 		protected void Awake()
 		{
 			this.lockID = "ARConnectionRequired";
+
+			if (ToolbarManager.ToolbarAvailable)
+			{
+				this.connectionTextures = new Dictionary<ConnectionStatus, string>();
+
+				this.connectionTextures[ConnectionStatus.None] = "AntennaRange/Textures/toolbarIconNoConnection";
+				this.connectionTextures[ConnectionStatus.Suboptimal] = "AntennaRange/Textures/toolbarIconSubOptimal";
+				this.connectionTextures[ConnectionStatus.Optimal] = "AntennaRange/Textures/toolbarIcon";
+
+				this.toolbarButton = ToolbarManager.Instance.add("AntennaRange", "ARConnectionStatus");
+
+				this.toolbarButton.TexturePath = this.connectionTextures[ConnectionStatus.None];
+				this.toolbarButton.Text = "AntennaRange";
+				this.toolbarButton.Visibility = new GameScenesVisibility(GameScenes.FLIGHT);
+				this.toolbarButton.Enabled = false;
+			}
 
 			GameEvents.onGameSceneLoadRequested.Add(this.onSceneChangeRequested);
 			GameEvents.onVesselChange.Add(this.onVesselChange);
@@ -116,11 +153,58 @@
 				// ...unlock the controls.
 				InputLockManager.RemoveControlLock(this.lockID);
 			}
+
+			if (this.toolbarButton != null && HighLogic.LoadedSceneIsFlight && FlightGlobals.ActiveVessel != null)
+			{
+				List<ModuleLimitedDataTransmitter> relays =
+					FlightGlobals.ActiveVessel.getModulesOfType<ModuleLimitedDataTransmitter>();
+
+				bool vesselCanTransmit = false;
+				bool vesselHasOptimalRelay = false;
+
+				foreach (ModuleLimitedDataTransmitter relay in relays)
+				{
+					if (!vesselCanTransmit && relay.CanTransmit())
+					{
+						vesselCanTransmit = true;
+					}
+
+					if (!vesselHasOptimalRelay && relay.transmitDistance <= (double)relay.nominalRange)
+					{
+						vesselHasOptimalRelay = true;
+					}
+
+					if (vesselCanTransmit && vesselHasOptimalRelay)
+					{
+						break;
+					}
+				}
+
+				if (vesselHasOptimalRelay)
+				{
+					this.currentConnectionStatus = ConnectionStatus.Optimal;
+				}
+				else if (vesselCanTransmit)
+				{
+					this.currentConnectionStatus = ConnectionStatus.Suboptimal;
+				}
+				else
+				{
+					this.currentConnectionStatus = ConnectionStatus.None;
+				}
+
+				this.toolbarButton.TexturePath = this.currentConnectionTexture;
+			}
 		}
 
 		protected void Destroy()
 		{
 			InputLockManager.RemoveControlLock(this.lockID);
+
+			if (this.toolbarButton != null)
+			{
+				this.toolbarButton.Destroy();
+			}
 
 			GameEvents.onGameSceneLoadRequested.Remove(this.onSceneChangeRequested);
 			GameEvents.onVesselChange.Remove(this.onVesselChange);
@@ -141,6 +225,13 @@
 			InputLockManager.RemoveControlLock(this.lockID);
 		}
 		#endregion
+
+		public enum ConnectionStatus
+		{
+			None,
+			Suboptimal,
+			Optimal
+		}
 	}
 }
 

--- a/Properties/AssemblyInfo.cs
+++ b/Properties/AssemblyInfo.cs
@@ -29,6 +29,8 @@
 using System.Reflection;
 using System.Runtime.CompilerServices;
 
+[assembly: KSPAssemblyDependency("ToadicusTools", 0, 0)]
+
 // Information about this assembly is defined by the following attributes.
 // Change them to the values specific to your project.
 [assembly: AssemblyTitle("AntennaRange")]
@@ -43,4 +45,3 @@
 //[assembly: AssemblyDelaySign(false)]
 //[assembly: AssemblyKeyFile("")]
 
-