diff --git a/src/RealAntennasProject/MapUI/GroundStationSiteNode.cs b/src/RealAntennasProject/MapUI/GroundStationSiteNode.cs index 3e628c1..8dbf1b9 100644 --- a/src/RealAntennasProject/MapUI/GroundStationSiteNode.cs +++ b/src/RealAntennasProject/MapUI/GroundStationSiteNode.cs @@ -3,9 +3,9 @@ namespace RealAntennas.MapUI { - class GroundStationSiteNode : ISiteNode + public class GroundStationSiteNode : ISiteNode { - RACommNode node; + public readonly RACommNode node; public GroundStationSiteNode(RACommNode node) { diff --git a/src/RealAntennasProject/MapUI/RACommNetUI.cs b/src/RealAntennasProject/MapUI/RACommNetUI.cs index 2b50a64..9be42b1 100644 --- a/src/RealAntennasProject/MapUI/RACommNetUI.cs +++ b/src/RealAntennasProject/MapUI/RACommNetUI.cs @@ -18,6 +18,8 @@ public class RACommNetUI : CommNet.CommNetUI public Color color3dB = XKCDColors.BarbiePink; public Color color10dB = XKCDColors.Lavender; + public readonly List groundStationSiteNodes = new List(); + private readonly List targetPoints = new List(); private readonly List targetPoints_out = new List(); private readonly List cone3Points = new List(); @@ -51,11 +53,21 @@ protected override void Start() Texture2D stationTexture = (GameDatabase.Instance.GetTexture(home.icon, false) is Texture2D tex) ? tex : defaultTex; siteNode.wayPoint.node.SetIcon(Sprite.Create(stationTexture, new Rect(0, 0, stationTexture.width, stationTexture.height), new Vector2(0.5f, 0.5f), 100f)); siteNode.wayPoint.node.OnUpdateVisible += home.OnUpdateVisible; + groundStationSiteNodes.Add(siteNode); } } RATelemetryUpdate.Install(); } + // If either one of these lists is nonempty, the links that are shown + // are exactly those in OverrideShownLinks, and the beamwidth cones are + // exactly those of the nodes in OverrideShownCones, regardless of the + // UI mode. + // The list is used and cleared by this class at the BetterLateThanNever + // timing of LateUpdate. + public List OverrideShownLinks { get; private set; } = new List(); + public List OverrideShownCones { get; private set; } = new List(); + private void GatherLinkLines(List linkList) { var settings = RACommNetScenario.MapUISettings; @@ -255,6 +267,7 @@ public void Init(Vector3d vertex, Vector3d axis, Vector3d normal, double angle) public Vector3d Midpoint => (end1 + end2) / 2; } + // Runs in LateUpdate at BetterLateThanNever (Timing5, 8008). protected override void UpdateDisplay() { //base.UpdateDisplay(); @@ -274,6 +287,17 @@ protected override void UpdateDisplay() if (RACommNetScenario.RACN is RACommNetwork commNet) { + if (OverrideShownLinks.Count > 0 || OverrideShownCones.Count > 0) + { + GatherLinkLines(OverrideShownLinks); + foreach (RACommNode node in OverrideShownCones) + { + GatherAntennaCones(node); + } + OverrideShownLinks.Clear(); + OverrideShownCones.Clear(); + return; + } if (CommNetUI.Mode == CommNetUI.DisplayMode.Network) { foreach (RACommNode node in commNet.Nodes) diff --git a/src/RealAntennasProject/Network/RACommLink.cs b/src/RealAntennasProject/Network/RACommLink.cs index 661b4ec..349fd86 100644 --- a/src/RealAntennasProject/Network/RACommLink.cs +++ b/src/RealAntennasProject/Network/RACommLink.cs @@ -2,7 +2,7 @@ namespace RealAntennas { - class RACommLink : CommNet.CommLink + public class RACommLink : CommNet.CommLink { private const double CostScalar = 1e5; public double FwdDataRate { get; set; } diff --git a/src/RealAntennasProject/Network/RACommNetHome.cs b/src/RealAntennasProject/Network/RACommNetHome.cs index 3cb601a..c6214a8 100644 --- a/src/RealAntennasProject/Network/RACommNetHome.cs +++ b/src/RealAntennasProject/Network/RACommNetHome.cs @@ -9,6 +9,9 @@ public class RACommNetHome : CommNetHome { protected static readonly string ModTag = "[RealAntennasCommNetHome] "; protected ConfigNode config = null; + protected bool isHome = true; + protected bool isControlSource = true; + protected bool isControlSourceMultiHop = true; private readonly double DriftTolerance = 10000.0; public string icon = "radio-antenna"; public RACommNode Comm => comm as RACommNode; @@ -31,6 +34,19 @@ public void Configure(ConfigNode node, CelestialBody body) lat = double.Parse(node.GetValue("lat")); lon = double.Parse(node.GetValue("lon")); alt = double.Parse(node.GetValue("alt")); + string value = null; + if (node.TryGetValue("isHome", ref value)) + { + isHome = bool.Parse(value); + } + if (node.TryGetValue("isControlSource", ref value)) + { + isControlSource = bool.Parse(value); + } + if (node.TryGetValue("isControlSourceMultiHop", ref value)) + { + isControlSourceMultiHop = bool.Parse(value); + } node.TryGetValue("icon", ref icon); SetTransformFromLatLonAlt(lat, lon, alt, body); } @@ -41,9 +57,9 @@ protected override void CreateNode() comm = new RACommNode(nodeTransform) { OnNetworkPreUpdate = new Action(OnNetworkPreUpdate), - isHome = true, - isControlSource = true, - isControlSourceMultiHop = true + isHome = isHome, + isControlSource = isControlSource, + isControlSourceMultiHop = isControlSourceMultiHop }; } comm.name = nodeName; @@ -72,7 +88,7 @@ protected override void CreateNode() } } - internal void OnUpdateVisible(KSP.UI.Screens.Mapview.MapNode mapNode, KSP.UI.Screens.Mapview.MapNode.IconData iconData) + public void OnUpdateVisible(KSP.UI.Screens.Mapview.MapNode mapNode, KSP.UI.Screens.Mapview.MapNode.IconData iconData) { Vector3d worldPos = ScaledSpace.LocalToScaledSpace(Comm.precisePosition); iconData.visible &= MapView.MapCamera.transform.InverseTransformPoint(worldPos).z >= 0 && !IsOccludedToCamera(Comm.precisePosition, body); diff --git a/src/RealAntennasProject/Physics.cs b/src/RealAntennasProject/Physics.cs index 2391acd..0188569 100644 --- a/src/RealAntennasProject/Physics.cs +++ b/src/RealAntennasProject/Physics.cs @@ -79,7 +79,7 @@ public static float PointingLoss(double angle, double beamwidth) else return math.lerp(9, 10, (norm - 0.86f) / 1); } public static float PointingLoss(RealAntenna ant, Vector3 origin) - => (ant.CanTarget && ant.ToTarget != Vector3.zero) ? PointingLoss(Vector3.Angle(origin - ant.Position, ant.ToTarget), ant.Beamwidth) : 0; + => (ant.CanTarget && !ant.IsTracking) ? PointingLoss(Vector3.Angle(origin - ant.Position, ant.ToTarget), ant.Beamwidth) : 0; public static float GainAtAngle(float gain, float angle) => gain - PointingLoss(math.abs(angle), Beamwidth(gain)); // Beamwidth is the 3dB full beamwidth contour, ~= the offset angle to the 10dB contour. diff --git a/src/RealAntennasProject/Precompute/Jobs.cs b/src/RealAntennasProject/Precompute/Jobs.cs index a3b7098..501c998 100644 --- a/src/RealAntennasProject/Precompute/Jobs.cs +++ b/src/RealAntennasProject/Precompute/Jobs.cs @@ -25,6 +25,7 @@ public struct ExtractDataJob : IJobParallelForDefer [WriteOnly] public NativeArray rxGain; [WriteOnly] public NativeArray rxBeamwidth; [WriteOnly] public NativeArray rxHome; + [WriteOnly] public NativeArray rxTracking; [WriteOnly] public NativeArray rxPos; [WriteOnly] public NativeArray rxDir; [WriteOnly] public NativeArray rxAMW; @@ -47,14 +48,15 @@ public void Execute(int index) txBeamwidth[index] = tx.beamwidth; txHome[index] = tx.isHome; txPos[index] = tx.position; - txDir[index] = tx.isHome ? (float3) (rx.position - tx.position) : tx.dir; + txDir[index] = tx.isTracking ? (float3) (rx.position - tx.position) : tx.dir; rxFreq[index] = rx.freq; rxGain[index] = rx.gain; rxBeamwidth[index] = rx.beamwidth; rxHome[index] = rx.isHome; + rxTracking[index] = rx.isTracking; rxPos[index] = rx.position; - rxDir[index] = rx.isHome ? (float3) (tx.position - rx.position) : rx.dir; + rxDir[index] = rx.isTracking ? (float3) (tx.position - rx.position) : rx.dir; rxAMW[index] = rx.AMW; } } @@ -79,7 +81,7 @@ public struct CalcAntennaBodyNoise : IJobParallelForDefer { [ReadOnly] public NativeArray occluders; [ReadOnly] public NativeArray rxPrecalcNoise; - [ReadOnly] public NativeArray rxHome; + [ReadOnly] public NativeArray rxTracking; [ReadOnly] public NativeArray rxPos; [ReadOnly] public NativeArray rxGain; [ReadOnly] public NativeArray rxBeamwidth; @@ -88,7 +90,7 @@ public struct CalcAntennaBodyNoise : IJobParallelForDefer [WriteOnly] public NativeArray bodyNoise; public void Execute(int index) { - bodyNoise[index] = rxHome[index] ? Precompute.NoiseFromOccluders(rxPos[index], rxGain[index], rxDir[index], rxFreq[index], rxBeamwidth[index], occluders) : rxPrecalcNoise[index]; + bodyNoise[index] = rxTracking[index] ? Precompute.NoiseFromOccluders(rxPos[index], rxGain[index], rxDir[index], rxFreq[index], rxBeamwidth[index], occluders) : rxPrecalcNoise[index]; } } diff --git a/src/RealAntennasProject/Precompute/Precompute.cs b/src/RealAntennasProject/Precompute/Precompute.cs index 8941f14..846c68f 100644 --- a/src/RealAntennasProject/Precompute/Precompute.cs +++ b/src/RealAntennasProject/Precompute/Precompute.cs @@ -14,6 +14,7 @@ public struct AntennaData internal float gain; internal float beamwidth; internal bool isHome; + internal bool isTracking; internal double3 position; internal float3 dir; internal float AMW; @@ -83,6 +84,7 @@ internal class Precompute private NativeArray rxGain; private NativeArray rxBeamwidth; private NativeArray rxHome; + private NativeArray rxTracking; private NativeArray rxPos; private NativeArray rxDir; private NativeArray rxAMW; @@ -229,6 +231,7 @@ public void DoThings(List bodies = null, List n rxGain = new NativeArray(allAntennaPairs.Length, Allocator.TempJob); rxBeamwidth = new NativeArray(allAntennaPairs.Length, Allocator.TempJob); rxHome = new NativeArray(allAntennaPairs.Length, Allocator.TempJob); + rxTracking = new NativeArray(allAntennaPairs.Length, Allocator.TempJob); rxPos = new NativeArray(allAntennaPairs.Length, Allocator.TempJob); rxDir = new NativeArray(allAntennaPairs.Length, Allocator.TempJob); rxAMW = new NativeArray(allAntennaPairs.Length, Allocator.TempJob); @@ -251,6 +254,7 @@ public void DoThings(List bodies = null, List n rxBeamwidth = rxBeamwidth, txHome = txHome, rxHome = rxHome, + rxTracking = rxTracking, txFreq = txFreq, rxFreq = rxFreq, txPower = txPower, @@ -324,7 +328,7 @@ public void DoThings(List bodies = null, List n { occluders = occluders, rxPrecalcNoise = rxPrecalcNoise, - rxHome = rxHome, + rxTracking = rxTracking, rxPos = rxPos, rxGain = rxGain, rxBeamwidth = rxBeamwidth, @@ -619,6 +623,7 @@ private void DisposeJobData() rxGain.Dispose(); rxBeamwidth.Dispose(); rxHome.Dispose(); + rxTracking.Dispose(); rxPos.Dispose(); rxDir.Dispose(); rxAMW.Dispose(); @@ -728,6 +733,7 @@ private NativeArray GatherAllAntennas(Dictionary gain = ra.Gain, beamwidth = ra.Beamwidth, isHome = node.isHome, + isTracking = ra.IsTracking, AMW = Physics.AntennaMicrowaveTemp(ra), encoder = new Encoder(ra.Encoder), maxSymbolRate = Convert.ToSingle(ra.SymbolRate), diff --git a/src/RealAntennasProject/RealAntenna.cs b/src/RealAntennasProject/RealAntenna.cs index cba9e71..a5046d3 100644 --- a/src/RealAntennasProject/RealAntenna.cs +++ b/src/RealAntennasProject/RealAntenna.cs @@ -38,7 +38,8 @@ public class RealAntenna public Vector3d PrecisePosition => ParentNode.precisePosition; public Vector3d TransformPosition => ParentNode.position; public virtual AntennaShape Shape => Gain <= Physics.MaxOmniGain ? AntennaShape.Omni : AntennaShape.Dish; - public virtual bool CanTarget => Shape != AntennaShape.Omni && (ParentNode == null || !ParentNode.isHome); + public bool IsTracking => Shape != AntennaShape.Omni && Target == null; + public virtual bool CanTarget => Shape != AntennaShape.Omni && !IsTracking; public Vector3 ToTarget => (CanTarget && Target != null) ? (Vector3) (Target.transform.position - Position) : Vector3.zero; private Targeting.AntennaTarget _target; @@ -114,7 +115,7 @@ public virtual void LoadFromConfigNode(ConfigNode config) AMWTemp = (config.HasValue("AMWTemp")) ? float.Parse(config.GetValue("AMWTemp")) : 290f; if (config.HasNode("TARGET")) Target = Targeting.AntennaTarget.LoadFromConfig(config.GetNode("TARGET"), this); - if (CanTarget && !(Target?.Validate() == true) && HighLogic.LoadedSceneHasPlanetarium) + else if (Shape != AntennaShape.Omni && (ParentNode == null || !ParentNode.isHome) && !(Target?.Validate() == true) && HighLogic.LoadedSceneHasPlanetarium) Target = Targeting.AntennaTarget.LoadFromConfig(SetDefaultTarget(), this); } diff --git a/src/RealAntennasProject/TechLevelInfo.cs b/src/RealAntennasProject/TechLevelInfo.cs index 0e3382b..8b3bf1f 100644 --- a/src/RealAntennasProject/TechLevelInfo.cs +++ b/src/RealAntennasProject/TechLevelInfo.cs @@ -23,8 +23,8 @@ public class TechLevelInfo public static bool initialized = false; - private static readonly Dictionary All = new Dictionary(); - public static int MaxTL { get; private set; } = -1; + public static readonly Dictionary All = new Dictionary(); + public static int MaxTL { get; set; } = -1; protected static readonly string ModTag = "[RealAntennas.TechLevelInfo] "; public TechLevelInfo() { }