< Summary

Class:TacticalPanelController
Assembly:bamlab.micromissiles
File(s):/github/workspace/Assets/Scripts/UI/TacticalPanelController.cs
Covered lines:0
Uncovered lines:164
Coverable lines:164
Total lines:257
Line coverage:0% (0 of 164)
Covered branches:0
Total branches:0
Covered methods:0
Total methods:29
Method coverage:0% (0 of 29)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
Awake()0%6200%
TacticalPanelController()0%2100%
Start()0%2100%
Update()0%2100%
OnDisable()0%2100%
InitializeController()0%6200%
SetupRadarUIGroup()0%2100%
ResetRadarUITransform()0%2100%
HandleRefreshTimer()0%6200%
UpdateSymbols()0%2100%
UpdateTrackSymbols[T](...)0%30500%
CreateSymbolPrefab()0%2100%
CreateOriginSymbol()0%2100%
CreateTrackSymbol(...)0%30500%
UpdateSymbolSpeedAlt(...)0%2100%
UpdateSymbolPosition(...)0%6200%
UpdateSymbolRotation(...)0%2100%
RemoveTrackSymbol(...)0%6200%
ClearAllSymbols()0%6200%
CycleRangeUp()0%2100%
CycleRangeDown()0%2100%
ZoomIn(...)0%2100%
ZoomOut(...)0%2100%
Pan(...)0%2100%
PanWithKeyboard(...)0%2100%
AdjustRadarScale(...)0%20400%
UpdateSymbolScale(...)0%2100%

File(s)

/github/workspace/Assets/Scripts/UI/TacticalPanelController.cs

#LineLine coverage
 1using UnityEngine;
 2using System.Collections.Generic;
 3using System.Linq;
 4
 5public class TacticalPanelController : MonoBehaviour {
 06  public static TacticalPanelController Instance { get; private set; } = null!;
 7
 08  private void Awake() {
 09    if (Instance == null) {
 010      Instance = this;
 011      InitializeController();
 012    } else {
 013      Destroy(gameObject);
 014    }
 015  }
 16
 17  [Tooltip("The UI group that contains the radar symbology elements")]
 18  [SerializeField]
 019  private GameObject _radarUIGroup = null!;
 20
 21  [SerializeField]
 22  [Tooltip("How often to refresh symbol positions (in seconds)")]
 023  private float _refreshRate = 0.1f;
 24
 25  [SerializeField]
 026  private float _keyboardPanSpeed = 500f;  // Adjust this value in the inspector
 27
 28  [SerializeField]
 029  private float _panelZoomSpeed = 10.0f;
 30
 031  private RectTransform _radarUIGroupRectTransform = null!;
 032  private IADS _iads = null!;
 33  private float _timeSinceLastRefresh;
 034  private readonly Dictionary<TrackFileData, GameObject> _trackSymbols =
 35      new Dictionary<TrackFileData, GameObject>();
 36
 037  private List<GameObject> _originSymbols = new List<GameObject>();
 38
 039  private TacticalPolarGridGraphic _polarGridGraphic = null!;
 40
 041  private void Start() {
 042    _iads = IADS.Instance;
 043    SetupRadarUIGroup();
 044    _timeSinceLastRefresh = 0f;
 045    CreateOriginSymbol();
 046  }
 47
 048  private void Update() {
 049    HandleRefreshTimer();
 050  }
 51
 052  private void OnDisable() {
 053    ClearAllSymbols();
 054  }
 55
 056  private void InitializeController() {
 57    // Initialize any controller-specific settings here if needed
 58    // Create polar grid
 059    _polarGridGraphic = _radarUIGroup.GetComponent<TacticalPolarGridGraphic>();
 060    if (_polarGridGraphic == null) {
 061      Debug.LogError("TacticalPolarGridGraphic not found on radar UI group");
 062    }
 063  }
 64
 065  private void SetupRadarUIGroup() {
 066    _radarUIGroupRectTransform = _radarUIGroup.GetComponent<RectTransform>();
 067    ResetRadarUITransform();
 068  }
 69
 070  private void ResetRadarUITransform() {
 071    _radarUIGroupRectTransform.localScale = Vector3.one;
 072    _radarUIGroupRectTransform.localPosition = Vector3.zero;
 073  }
 74
 075  private void HandleRefreshTimer() {
 076    _timeSinceLastRefresh += Time.unscaledDeltaTime;
 77
 078    if (_timeSinceLastRefresh >= _refreshRate) {
 079      UpdateSymbols();
 080      _timeSinceLastRefresh = 0f;
 081    }
 082  }
 83
 084  private void UpdateSymbols() {
 085    UpdateTrackSymbols(_iads.GetThreatTracks());
 086    UpdateTrackSymbols(_iads.GetInterceptorTracks());
 087  }
 88
 89  private void UpdateTrackSymbols<T>(List<T> currentTracks)
 090      where T : TrackFileData {
 91    // Remove inactive symbols
 092    var tracksToRemove =
 93        _trackSymbols.Keys.OfType<T>().Where(track => !currentTracks.Contains(track)).ToList();
 94
 095    foreach (var track in tracksToRemove) {
 096      RemoveTrackSymbol(track);
 097    }
 98
 99    // Update or create active symbols
 0100    foreach (var track in currentTracks) {
 0101      if (track.Status == TrackStatus.DESTROYED) {
 0102        RemoveTrackSymbol(track);
 0103        continue;
 104      }
 105
 0106      if (_trackSymbols.TryGetValue(track, out GameObject symbolObj)) {
 0107        UpdateSymbolPosition(symbolObj, track.Agent.transform.position);
 0108        UpdateSymbolScale(symbolObj);
 0109        UpdateSymbolRotation(symbolObj, track.Agent.transform.forward);
 0110        UpdateSymbolSpeedAlt(symbolObj.GetComponent<TacticalSymbol>(), track);
 0111      } else {
 0112        CreateTrackSymbol(track);
 0113      }
 0114    }
 0115  }
 116
 0117  private GameObject CreateSymbolPrefab() {
 0118    return Instantiate(Resources.Load<GameObject>("Prefabs/Symbols/SymbolPrefab"),
 119                       _radarUIGroupRectTransform);
 0120  }
 121
 0122  private void CreateOriginSymbol() {
 0123    GameObject symbolPrefab = CreateSymbolPrefab();
 0124    symbolPrefab.GetComponent<TacticalSymbol>().SetSprite("friendly_destroyer_present");
 0125    symbolPrefab.GetComponent<TacticalSymbol>().DisableDirectionArrow();
 0126    symbolPrefab.GetComponent<TacticalSymbol>().SetSpeedAlt("");
 0127    symbolPrefab.GetComponent<TacticalSymbol>().SetType("");
 0128    symbolPrefab.GetComponent<TacticalSymbol>().SetUniqueDesignator("");
 0129    _originSymbols.Add(symbolPrefab);
 0130  }
 131
 0132  private void CreateTrackSymbol(TrackFileData trackFile) {
 0133    GameObject symbolObj = CreateSymbolPrefab();
 0134    TacticalSymbol tacticalSymbol = symbolObj.GetComponent<TacticalSymbol>();
 135
 136    // Set common properties
 0137    tacticalSymbol.SetSprite(trackFile.Agent.staticConfig.VisualizationConfig?.SymbolPresent);
 0138    tacticalSymbol.SetDirectionArrowRotation(
 139        Mathf.Atan2(trackFile.Agent.GetVelocity().z, trackFile.Agent.GetVelocity().x) *
 140        Mathf.Rad2Deg);
 141
 0142    UpdateSymbolSpeedAlt(tacticalSymbol, trackFile);
 143
 144    // Set type-specific properties
 0145    if (trackFile is ThreatData) {
 0146      tacticalSymbol.SetType(trackFile.Agent.staticConfig.AgentType.ToString());
 0147    } else if (trackFile is InterceptorData) {
 0148      tacticalSymbol.SetType("Interceptor");
 0149    }
 150
 0151    tacticalSymbol.SetUniqueDesignator(trackFile.TrackID);
 152
 0153    UpdateSymbolPosition(symbolObj, trackFile.Agent.transform.position);
 0154    UpdateSymbolRotation(symbolObj, trackFile.Agent.transform.forward);
 0155    UpdateSymbolScale(symbolObj);
 156
 0157    _trackSymbols.Add(trackFile, symbolObj);
 0158  }
 159
 0160  private void UpdateSymbolSpeedAlt(TacticalSymbol tacticalSymbol, TrackFileData trackFile) {
 0161    tacticalSymbol.SetSpeedAlt(
 162        $"{Utilities.ConvertMpsToKnots(trackFile.Agent.GetVelocity().magnitude):F0}kts/" +
 163        $"{Utilities.ConvertMetersToFeet(trackFile.Agent.transform.position.y):F0}ft");
 0164  }
 165
 166  /// Updates the position of a symbol based on the threat's real-world position.
 0167  private void UpdateSymbolPosition(GameObject symbolObj, Vector3 threatPosition) {
 0168    if (_polarGridGraphic == null) {
 0169      Debug.LogError("TacticalPolarGridGraphic reference is missing.");
 0170      return;
 171    }
 172
 173    // Get the current scale factor from the grid
 0174    float scaleFactor = _polarGridGraphic.CurrentScaleFactor;
 175
 176    // Assuming threatPosition is in meters, convert to the grid's scale
 177    // Adjust the division factor as per your real-world scaling
 0178    float scaleDivisionFactor = 1000f;  // Example: 1000 meters = 1 unit on grid
 179
 0180    Vector3 scaledPosition = new Vector3(threatPosition.z / scaleDivisionFactor,
 181                                         threatPosition.x / scaleDivisionFactor, 0f);
 182
 183    // Apply the scaleFactor to ensure positioning aligns with grid scaling
 0184    symbolObj.transform.localPosition = scaledPosition * scaleFactor;
 0185  }
 186
 0187  private void UpdateSymbolRotation(GameObject symbolObj, Vector3 forward) {
 0188    symbolObj.GetComponent<TacticalSymbol>().SetDirectionArrowRotation(
 189        -1 * Mathf.Atan2(forward.z, forward.x) * Mathf.Rad2Deg);
 0190  }
 191
 0192  private void RemoveTrackSymbol(TrackFileData trackFile) {
 0193    if (_trackSymbols.TryGetValue(trackFile, out GameObject symbolObj)) {
 0194      Destroy(symbolObj);
 0195      _trackSymbols.Remove(trackFile);
 0196    }
 0197  }
 198
 0199  private void ClearAllSymbols() {
 0200    foreach (var symbol in _trackSymbols.Values) {
 0201      Destroy(symbol);
 0202    }
 0203    _trackSymbols.Clear();
 0204  }
 205
 0206  public void CycleRangeUp() {
 0207    _polarGridGraphic.CycleRangeUp();
 0208  }
 209
 0210  public void CycleRangeDown() {
 0211    _polarGridGraphic.CycleRangeDown();
 0212  }
 213
 0214  public void ZoomIn(float amount) {
 0215    AdjustRadarScale(amount * _panelZoomSpeed);
 0216  }
 217
 0218  public void ZoomOut(float amount) {
 0219    AdjustRadarScale(-amount * _panelZoomSpeed);
 0220  }
 221
 0222  public void Pan(Vector2 delta) {
 0223    Vector3 currentPos = _radarUIGroupRectTransform.localPosition;
 0224    _radarUIGroupRectTransform.localPosition =
 225        new Vector3(currentPos.x + delta.x, currentPos.y + delta.y, currentPos.z);
 0226  }
 227
 0228  public void PanWithKeyboard(Vector2 direction) {
 0229    Vector2 delta = direction * _keyboardPanSpeed * Time.unscaledDeltaTime;
 0230    Pan(delta);
 0231  }
 232
 233  /// Adjusts the radar scale by the specified amount.
 0234  private void AdjustRadarScale(float amount) {
 0235    Vector3 newScale = _radarUIGroupRectTransform.localScale + new Vector3(amount, amount, 0f);
 236
 237    // Prevent negative or too small scaling
 0238    if (newScale.x < 0.01f || newScale.y < 0.01f) {
 0239      return;
 240    }
 241
 0242    _radarUIGroupRectTransform.localScale = newScale;
 243
 244    // Update all existing symbols' scales
 0245    foreach (var symbol in _trackSymbols.Values) {
 0246      UpdateSymbolScale(symbol);
 0247    }
 248    // Temporarily necessary until we implement IADS vessel system
 0249    UpdateSymbolScale(_originSymbols[0]);
 0250  }
 251
 0252  private void UpdateSymbolScale(GameObject symbolObj) {
 253    // Calculate inverse scale to maintain constant visual size
 0254    float inverseScale = 2f / _radarUIGroupRectTransform.localScale.x;
 0255    symbolObj.transform.localScale = new Vector3(inverseScale, inverseScale, 1f);
 0256  }
 257}