using Robust.Client.Interfaces.Debugging; using Robust.Shared.Interfaces.Network; using Robust.Shared.IoC; using Robust.Shared.Network.Messages; using System; using System.Collections.Generic; using Robust.Client.Graphics.Overlays; using Robust.Client.Graphics.Drawing; using Robust.Shared.Maths; using Robust.Client.Interfaces.Graphics.Overlays; using Robust.Shared.Timing; using Robust.Shared.Interfaces.Timing; namespace Robust.Client.Debugging { internal class DebugDrawingManager : IDebugDrawingManager { #pragma warning disable 649 [Dependency] private readonly IClientNetManager _net; [Dependency] private readonly IOverlayManager _overlayManager; [Dependency] private readonly IGameTiming _gameTimer; #pragma warning restore 649 private readonly List raysWithLifeTime = new List(); private bool _debugDrawRays; private struct RayWithLifetime { public Vector2 RayOrigin; public Vector2 RayHit; public TimeSpan LifeTime; public bool DidActuallyHit; } public bool DebugDrawRays { get => _debugDrawRays; set { if (value == DebugDrawRays) { return; } _debugDrawRays = value; if (value) { _overlayManager.AddOverlay(new DebugDrawRayOverlay(this)); } else { _overlayManager.RemoveOverlay(nameof(DebugDrawRayOverlay)); } } } public TimeSpan DebugRayLifetime { get; set; } = TimeSpan.FromSeconds(5); public void Initialize() { _net.RegisterNetMessage(MsgRay.NAME, HandleDrawRay); } private void HandleDrawRay(MsgRay msg) { // Rays are disposed with DebugDrawRayOverlay.FrameUpdate. // We don't accept incoming rays when that's off because else they'd pile up constantly. if (!_debugDrawRays) { return; } var newRayWithLifetime = new RayWithLifetime { DidActuallyHit = msg.DidHit, RayOrigin = msg.RayOrigin, RayHit = msg.RayHit, LifeTime = _gameTimer.RealTime + DebugRayLifetime }; raysWithLifeTime.Add(newRayWithLifetime); } private sealed class DebugDrawRayOverlay : Overlay { private readonly DebugDrawingManager _owner; public override OverlaySpace Space => OverlaySpace.WorldSpace; public DebugDrawRayOverlay(DebugDrawingManager owner) : base(nameof(DebugDrawRayOverlay)) { _owner = owner; } protected override void Draw(DrawingHandleBase handle) { foreach (var ray in _owner.raysWithLifeTime) { handle.DrawLine( ray.RayOrigin, ray.RayHit, ray.DidActuallyHit ? Color.Yellow : Color.Magenta); } } internal override void FrameUpdate(FrameEventArgs args) { base.FrameUpdate(args); _owner.raysWithLifeTime.RemoveAll(r => r.LifeTime < _owner._gameTimer.RealTime); } } } }