Refigured the whole way target relays are found; mostly works. PrettyLinesDev2_Broken
[AntennaRange.git] / ARMapRenderer.cs
blob:a/ARMapRenderer.cs -> blob:b/ARMapRenderer.cs
--- a/ARMapRenderer.cs
+++ b/ARMapRenderer.cs
@@ -2,7 +2,7 @@
 //
 // ARMapRenderer.cs
 //
-// Copyright © 2014, toadicus
+// Copyright © 2014-2015, toadicus
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without modification,
@@ -26,19 +26,40 @@
 // 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.
 
+#pragma warning disable 1591
+
 using KSP;
 using System;
 using System.Collections.Generic;
-using ToadicusTools;
+using ToadicusTools.Extensions;
+using ToadicusTools.DebugTools;
 using UnityEngine;
 
 namespace AntennaRange
 {
 	public class ARMapRenderer : MonoBehaviour
 	{
+		#if BENCH
+		private static ulong updateCount = 0u;
+		private static ulong updateTimer = 0u;
+		private readonly static RollingAverage averager = new RollingAverage();
+		private static long twiceAverageTime = long.MaxValue;
+		#endif
+
 		#region Fields
 		private Dictionary<Guid, LineRenderer> vesselLineRenderers;
-		private Dictionary<Guid, bool> vesselFrameCache;
+
+		// Debug Stuff
+		#pragma warning disable 649
+		private System.Diagnostics.Stopwatch timer;
+		private PooledDebugLogger log;
+		private long relayStart;
+		private long start;
+		#pragma warning restore 649
+
+		#pragma warning disable 414
+		private Color thisColor;
+		#pragma warning restore 414
 		#endregion
 
 		#region Properties
@@ -46,26 +67,23 @@
 		{
 			get
 			{
-				if (this.vesselLineRenderers == null)
-				{
-					this.vesselLineRenderers = new Dictionary<Guid, LineRenderer>();
-				}
-
-				if (!this.vesselLineRenderers.ContainsKey(idx))
+				LineRenderer lr;
+
+				if (!this.vesselLineRenderers.TryGetValue(idx, out lr))
 				{
 					GameObject obj = new GameObject();
 					obj.layer = 31;
 
-					LineRenderer lr = obj.AddComponent<LineRenderer>();
-
-					lr.SetColors(Color.green, Color.green);
-					lr.material = new Material(Shader.Find("Particles/Additive"));
-					lr.SetVertexCount(2);
+					lr = obj.AddComponent<LineRenderer>();
+
+					lr.material = MapView.OrbitLinesMaterial;
 
 					this.vesselLineRenderers[idx] = lr;
-				}
-
-				return this.vesselLineRenderers[idx];
+
+					return lr;
+				}
+
+				return lr;
 			}
 		}
 		#endregion
@@ -73,23 +91,36 @@
 		#region MonoBehaviour Lifecycle
 		private void Awake()
 		{
-			this.vesselLineRenderers = new Dictionary<Guid, LineRenderer>();
-			this.vesselFrameCache = new Dictionary<Guid, bool>();
+			if (ARConfiguration.PrettyLines)
+			{
+				this.vesselLineRenderers = new Dictionary<Guid, LineRenderer>();
+			}
+
+			#if DEBUG || BENCH
+			this.timer = new System.Diagnostics.Stopwatch();
+			#endif
+			#if DEBUG
+			this.log = PooledDebugLogger.Get(this);
+			#endif
 		}
 
 		private void OnPreCull()
 		{
-			if (!HighLogic.LoadedSceneIsFlight || !MapView.MapIsEnabled)
-			{
-				this.Cleanup();
+			if (!HighLogic.LoadedSceneIsFlight || !MapView.MapIsEnabled || !ARConfiguration.PrettyLines)
+			{
+				this.Cleanup(!HighLogic.LoadedSceneIsFlight);
 
 				return;
 			}
 
-			Tools.DebugLogger log = Tools.DebugLogger.New(this);
+			#if DEBUG || BENCH
+			timer.Restart();
+			#endif
 
 			try
 			{
+				log.Clear();
+
 				log.AppendFormat("OnPreCull.\n");
 
 				log.AppendFormat("\tMapView: Draw3DLines: {0}\n" +
@@ -100,178 +131,197 @@
 					MapView.MapCamera.Distance
 				);
 
-				this.vesselFrameCache.Clear();
-
-				log.AppendLine("vesselFrameCache cleared.");
-
-				if (FlightGlobals.ready && FlightGlobals.Vessels != null)
-				{
-					log.AppendLine("FlightGlobals ready and Vessels list not null.");
-
-					foreach (Vessel vessel in FlightGlobals.Vessels)
+				log.AppendLine("FlightGlobals ready and Vessels list not null.");
+
+				IAntennaRelay relay;
+
+				for (int i = 0; i < ARFlightController.UsefulRelays.Count; i++)
+				{
+					relay = ARFlightController.UsefulRelays[i];
+
+					if (relay == null)
 					{
-						if (vessel == null)
-						{
-							log.AppendFormat("Skipping vessel {0} altogether because it is null.\n");
-							continue;
-						}
-
-						log.AppendFormat("Checking vessel {0}.\n", vessel.vesselName);
-
-						switch (vessel.vesselType)
-						{
-							case VesselType.Debris:
-							case VesselType.EVA:
-							case VesselType.Unknown:
-							case VesselType.SpaceObject:
-								log.AppendFormat("\tDiscarded because vessel is of invalid type {0}\n",
-									vessel.vesselType);
-								continue;
-						}
-
-						log.Append("\tChecking connection status...\n");
-
-						/*if (vessel.HasConnectedRelay())
-						{
-							log.AppendLine("\tHas a connection, checking for the best relay to use for the line.");*/
-
-							IAntennaRelay vesselRelay = null;
-							float bestScore = float.PositiveInfinity;
-							float relayScore = float.NaN;
-
-							foreach (IAntennaRelay relay in RelayDatabase.Instance[vessel].Values)
-							{
-								relayScore = (float)relay.transmitDistance / relay.maxTransmitDistance;
-
-								if (relayScore < bestScore)
-								{
-									bestScore = relayScore;
-									vesselRelay = relay as IAntennaRelay;
-								}
-							}
-
-							if (vesselRelay != null)
-							{
-								log.AppendFormat("\t...picked relay {0} with a score of {1}", 
-									vesselRelay, relayScore
-								);
-
-								this.SetRelayVertices(vesselRelay);
-							}
-						/*}
-						else if (this.vesselLineRenderers.ContainsKey(vessel.id))
-						{
-							log.AppendLine("\tDisabling line because vessel has no connection.");
-							this[vessel.id].enabled = false;
-						}*/
+						log.AppendFormat("\n\tGot null relay, skipping");
+						continue;
 					}
-				}
-			}
+
+					log.AppendFormat("\n\tDrawing pretty lines for useful relay {0}", relay);
+					
+					#if DEBUG
+					start = timer.ElapsedMilliseconds;
+					#endif
+
+					this.SetRelayVertices(relay);
+
+					log.AppendFormat("\n\tSet relay vertices for {0} in {1}ms",
+						relay, timer.ElapsedMilliseconds - start);
+				}
+			}
+			catch (Exception ex)
+			{
+				this.LogError("Caught {0}: {1}\n{2}\n", ex.GetType().Name, ex.ToString(), ex.StackTrace.ToString());
+				this.Cleanup(false);
+			}
+			#if DEBUG
 			finally
 			{
+				log.AppendFormat("\n\tOnPreCull finished in {0}ms\n", timer.ElapsedMilliseconds);
+
 				log.Print();
 			}
+			#endif
+
+			#if BENCH
+			ARMapRenderer.updateCount++;
+			ARMapRenderer.updateTimer += (ulong)this.timer.ElapsedTicks;
+
+			if (ARMapRenderer.updateCount >= (ulong)(8d / Time.smoothDeltaTime))
+			{
+				ARMapRenderer.averager.AddItem((double)ARMapRenderer.updateTimer / (double)ARMapRenderer.updateCount);
+				ARMapRenderer.updateTimer = 0u;
+				ARMapRenderer.updateCount = 0u;
+				ARMapRenderer.twiceAverageTime = (long)(ARMapRenderer.averager.Average * 2d);
+			}
+
+			if (this.timer.ElapsedTicks > ARMapRenderer.twiceAverageTime)
+			{
+				this.Log("PreCull took significant longer than usual ({0:S3}s vs {1:S3}s)",
+					(double)this.timer.ElapsedTicks / (double)System.Diagnostics.Stopwatch.Frequency,
+					ARMapRenderer.averager.Average / (double)System.Diagnostics.Stopwatch.Frequency
+				);
+			}
+			#endif
 		}
 
 		private void OnDestroy()
 		{
-			this.Cleanup();
-
-			print("ARMapRenderer: Destroyed.");
+			this.Cleanup(true);
+
+			this.Log("Destroyed");
 		}
 		#endregion
 
+		#region Utility
 		private void SetRelayVertices(IAntennaRelay relay)
 		{
-			do
-			{
-				if (this.vesselFrameCache.ContainsKey(relay.vessel.id))
-				{
-					break;
-				}
-
-				LineRenderer renderer = this[relay.vessel.id];
-
-				Vector3d start;
-				Vector3d end;
-
-				renderer.enabled = true;
-
-				if (!relay.CanTransmit())
-				{
-					renderer.SetColors(Color.red, Color.red);
+			log.AppendFormat("\n\t\tDrawing line for relay chain starting at {0}.", relay);
+
+			if (relay.vessel == null)
+			{
+				log.Append("\n\t\tvessel is null, bailing out");
+				return;
+			}
+
+			LineRenderer renderer = this[relay.vessel.id];
+			Vector3d start = ScaledSpace.LocalToScaledSpace(relay.vessel.GetWorldPos3D());
+
+			float lineWidth;
+			float d = Screen.height / 2f + 0.01f;
+
+			if (MapView.Draw3DLines)
+			{
+				lineWidth = 0.005859375f * MapView.MapCamera.Distance;
+			}
+			else
+			{
+				lineWidth = 2f;
+
+				start = MapView.MapCamera.camera.WorldToScreenPoint(start);
+
+				start.z = start.z >= 0f ? d : -d;
+			}
+
+			renderer.SetWidth(lineWidth, lineWidth);
+
+			renderer.SetPosition(0, start);
+
+			int idx = 0;
+
+			#if DEBUG
+			relayStart = timer.ElapsedMilliseconds;
+			#endif
+
+			Vector3d nextPoint;
+
+			renderer.enabled = true;
+
+			if (!relay.CanTransmit())
+			{
+				thisColor = Color.red;
+			}
+			else
+			{
+				if (relay.LinkStatus == ConnectionStatus.Optimal)
+				{
+					thisColor = Color.green;
 				}
 				else
 				{
-					if (relay.transmitDistance < relay.nominalTransmitDistance)
+					thisColor = Color.yellow;
+				}
+			}
+
+			if (relay.KerbinDirect)
+			{
+				nextPoint = ScaledSpace.LocalToScaledSpace(AntennaRelay.Kerbin.position);
+			}
+			else
+			{
+				if (relay.targetRelay == null || relay.targetRelay.vessel == null)
+				{
+					this.LogError(
+						"SetRelayVertices: relay {0} has null target relay or vessel when not KerbinDirect, bailing out!",
+						relay
+					);
+
+					renderer.enabled = false;
+					return;
+				}
+
+				nextPoint = ScaledSpace.LocalToScaledSpace(relay.targetRelay.vessel.GetWorldPos3D());
+			}
+
+			renderer.SetColors(thisColor, thisColor);
+
+			if (!MapView.Draw3DLines)
+			{
+				nextPoint = MapView.MapCamera.camera.WorldToScreenPoint(nextPoint);
+				nextPoint.z = nextPoint.z >= 0f ? d : -d;
+			}
+
+			idx++;
+
+			renderer.SetVertexCount(idx + 1);
+			renderer.SetPosition(idx, nextPoint);
+
+			log.AppendFormat("\n\t\t\t...finished segment in {0} ms", timer.ElapsedMilliseconds - relayStart);
+		}
+
+		private void Cleanup(bool freeObjects)
+		{
+			if (this.vesselLineRenderers != null && this.vesselLineRenderers.Count > 0)
+			{
+				IEnumerator<LineRenderer> enumerator = this.vesselLineRenderers.Values.GetEnumerator();
+				LineRenderer lineRenderer;
+
+				while (enumerator.MoveNext())
+				{
+					lineRenderer = enumerator.Current;
+					lineRenderer.enabled = false;
+
+					if (freeObjects)
 					{
-						renderer.SetColors(Color.green, Color.green);
+						GameObject.Destroy(lineRenderer.gameObject);
 					}
-					else
-					{
-						renderer.SetColors(Color.yellow, Color.yellow);
-					}
-				}
-
-				start = ScaledSpace.LocalToScaledSpace(relay.vessel.GetWorldPos3D());
-
-				if (relay.KerbinDirect)
-				{
-					end = ScaledSpace.LocalToScaledSpace(AntennaRelay.Kerbin.position);
-				}
-				else
-				{
-					end = ScaledSpace.LocalToScaledSpace(relay.targetRelay.vessel.GetWorldPos3D());
-				}
-
-				float lineWidth;
-
-				if (MapView.Draw3DLines)
-				{
-					lineWidth = 0.004f * MapView.MapCamera.Distance;
-				}
-				else
-				{
-					lineWidth = 1f;
-
-					start = MapView.MapCamera.camera.WorldToScreenPoint(start);
-					end = MapView.MapCamera.camera.WorldToScreenPoint(end);
-
-					float d = Screen.height / 2f + 0.01f;
-					start.z = start.z >= 0f ? d : -d;
-					end.z = end.z >= 0f ? d : -d;
-				}
-
-				renderer.SetWidth(lineWidth, lineWidth);
-
-				renderer.SetPosition(0, start);
-				renderer.SetPosition(1, end);
-
-				this.vesselFrameCache[relay.vessel.id] = true;
-
-				relay = relay.nearestRelay;
-			}
-			while (relay != null);
-		}
-
-		public void Cleanup()
-		{
-			if (this.vesselLineRenderers != null && this.vesselLineRenderers.Count > 0)
-			{
-				foreach (LineRenderer lineRenderer in this.vesselLineRenderers.Values)
-				{
-					lineRenderer.enabled = false;
-					GameObject.Destroy(lineRenderer.gameObject);
-				}
-				this.vesselLineRenderers.Clear();
-			}
-
-			if (this.vesselFrameCache != null && this.vesselFrameCache.Count > 0)
-			{
-				this.vesselFrameCache.Clear();
-			}
-		}
+				}
+
+				if (freeObjects)
+				{
+					this.vesselLineRenderers.Clear();
+				}
+			}
+		}
+		#endregion
 	}
 }
 
-