using System.Numerics;
using Content.Shared.Shuttles.Components;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Shared.Enums;
using Robust.Shared.Map.Components;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
namespace Content.Client.Shuttles;
///
/// Plays a visualization whenever a shuttle is arriving from FTL.
///
public sealed class FtlArrivalOverlay : Overlay
{
private static readonly ProtoId UnshadedShader = "unshaded";
public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowEntities;
private EntityLookupSystem _lookups;
private SharedMapSystem _maps;
private SharedTransformSystem _transforms;
private SpriteSystem _sprites;
[Dependency] private readonly IEntityManager _entManager = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly IPrototypeManager _protos = default!;
private readonly HashSet> _visualizers = new();
private ShaderInstance _shader;
public FtlArrivalOverlay()
{
IoCManager.InjectDependencies(this);
_lookups = _entManager.System();
_transforms = _entManager.System();
_maps = _entManager.System();
_sprites = _entManager.System();
_shader = _protos.Index(UnshadedShader).Instance();
}
protected override bool BeforeDraw(in OverlayDrawArgs args)
{
_visualizers.Clear();
_lookups.GetEntitiesOnMap(args.MapId, _visualizers);
return _visualizers.Count > 0;
}
protected override void Draw(in OverlayDrawArgs args)
{
args.WorldHandle.UseShader(_shader);
foreach (var (uid, comp) in _visualizers)
{
var grid = comp.Grid;
if (!_entManager.TryGetComponent(grid, out MapGridComponent? mapGrid))
continue;
var texture = _sprites.GetFrame(comp.Sprite, TimeSpan.FromSeconds(comp.Elapsed), loop: false);
comp.Elapsed += (float) _timing.FrameTime.TotalSeconds;
// Need to manually transform the viewport in terms of the visualizer entity as the grid isn't in position.
var (_, _, worldMatrix, invMatrix) = _transforms.GetWorldPositionRotationMatrixWithInv(uid);
args.WorldHandle.SetTransform(worldMatrix);
var localAABB = invMatrix.TransformBox(args.WorldBounds);
var tilesEnumerator = _maps.GetLocalTilesEnumerator(grid, mapGrid, localAABB);
while (tilesEnumerator.MoveNext(out var tile))
{
var bounds = _lookups.GetLocalBounds(tile, mapGrid.TileSize);
args.WorldHandle.DrawTextureRect(texture, bounds);
}
}
args.WorldHandle.UseShader(null);
args.WorldHandle.SetTransform(Matrix3x2.Identity);
}
}