using System.Collections.Generic; using System.Numerics; using Robust.Client.Graphics; using Robust.Shared.Console; using Robust.Shared.Containers; using Robust.Shared.Enums; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Maths; using Robust.Shared.Physics.Dynamics; using Robust.Shared.Utility; using Color = Robust.Shared.Maths.Color; namespace Robust.Client.GameObjects; public sealed class DebugEntityLookupCommand : LocalizedCommands { public override string Command => "togglelookup"; public override void Execute(IConsoleShell shell, string argStr, string[] args) { EntitySystem.Get().Enabled ^= true; } } public sealed class DebugEntityLookupSystem : EntitySystem { public bool Enabled { get => _enabled; set { if (_enabled == value) return; _enabled = value; if (_enabled) { IoCManager.Resolve().AddOverlay( new EntityLookupOverlay( EntityManager, EntityManager.System(), EntityManager.System())); } else { IoCManager.Resolve().RemoveOverlay(); } } } private bool _enabled; } public sealed class EntityLookupOverlay : Overlay { private readonly IEntityManager _entityManager; private readonly EntityLookupSystem _lookup; private readonly SharedTransformSystem _transform; private EntityQuery _xformQuery; public override OverlaySpace Space => OverlaySpace.WorldSpace; public EntityLookupOverlay(IEntityManager entManager, EntityLookupSystem lookup, SharedTransformSystem transform) { _entityManager = entManager; _lookup = lookup; _xformQuery = entManager.GetEntityQuery(); _transform = transform; } protected internal override void Draw(in OverlayDrawArgs args) { var worldHandle = args.WorldHandle; var worldBounds = args.WorldBounds; // TODO: Static version _lookup.FindLookupsIntersecting(args.MapId, worldBounds, (uid, lookup) => { var (_, rotation, matrix, invMatrix) = _transform.GetWorldPositionRotationMatrixWithInv(uid); worldHandle.SetTransform(matrix); var lookupAABB = invMatrix.TransformBox(worldBounds); var ents = new List(); lookup.DynamicTree.QueryAabb(ref ents, static (ref List state, in FixtureProxy value) => { state.Add(value.Entity); return true; }, lookupAABB); lookup.StaticTree.QueryAabb(ref ents, static (ref List state, in FixtureProxy value) => { state.Add(value.Entity); return true; }, lookupAABB); lookup.StaticSundriesTree.QueryAabb(ref ents, static (ref List state, in EntityUid value) => { state.Add(value); return true; }, lookupAABB); lookup.SundriesTree.QueryAabb(ref ents, static (ref List state, in EntityUid value) => { state.Add(value); return true; }, lookupAABB); foreach (var ent in ents) { if (_entityManager.Deleted(ent)) continue; var xform = _xformQuery.GetComponent(ent); //DebugTools.Assert(!ent.IsInContainer(_entityManager)); var (entPos, entRot) = _transform.GetWorldPositionRotation(ent); var lookupPos = Vector2.Transform(entPos, invMatrix); var lookupRot = entRot - rotation; var aabb = _lookup.GetAABB(ent, lookupPos, lookupRot, xform, _xformQuery); worldHandle.DrawRect(aabb, Color.Blue.WithAlpha(0.2f)); } }); worldHandle.SetTransform(Matrix3x2.Identity); } }