mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-15 03:30:53 +01:00
* Physics worlds * Paul's a good boy * Build working * Ingame and not lagging to hell * Why didn't you commit ahhhhh * Hard collisions working * Solver parity * Decent broadphase work done * BroadPhase outline done * BroadPhase working * waiting for pvs * Fix static PVS AABB * Stop static bodies from awakening * Optimise a bunch of stuff * Even more broadphase stuff * I'm fucking stupid * Optimise fixture updates * Collision solver start * Building * A is for Argumentative * Fix contact caching island flags * Circle shapes actually workeded * Damping * DS2 consumables only * Slightly more stable * Even slightlier more stablier * VV your heart out * Initial joint support * 90% of joints I just wanted to push as I'd scream if I lost progress * JOINT PURGATORY * Joints barely functional lmao * Okay these joints slightly more functional * Remove station FrictionJoint * Also that * Some Box2D ports * Cleanup mass * Edge shape * Active contacts * Fix active contacts * Optimise active contacts even more * Boxes be stacking * I would die for smug oh my fucking god * In which everything is fixed * Distance joints working LETS GO * Remove frequency on distancejoint * Fix some stuff and break joints * Crashing fixed mehbeh * ICollideSpecial and more resilience * auto-clear * showbb vera * Slap that TODO in there * Fix restartround crash * Random fixes * Fix fixture networking * Add intersection method for broadphase * Fix contacts * Licenses done * Optimisations * Fix wall clips * Config caching for island * allocations optimisations * Optimise casts * Optimise events queue for physics * Contact manager optimisations * Optimise controllers * Sloth joint or something idk * Controller graph * Remove content cvar * Random cleanup * Finally remove VirtualController * Manifold structs again * Optimise this absolute retardation * Optimise * fix license * Cleanup physics interface * AHHHHHHHHHHHHH * Fix collisions again * snivybus * Fix potential nasty manifold bug * Tests go snivy * Disable prediction for now * Spans * Fix ShapeTypes * fixes * ch ch changeesss * Kinematic idea * Prevent static bodies from waking * Pass WorldAABB to MoveEvent * Fix collisions * manifold structs fucking WOOORRKKKINNGGG * Better pushing * Fix merge ickies * Optimise MoveEvents * Use event for collisions performance * Fix content tests * Do not research tests * Fix most conflicts * Paul's trying to kill me * Maybe collisions work idk * Make us whole again * Smug is also trying to kill me * nani * shitty collisions * Settling * Do not research collisions * SHIP IT * Fix joints * PVS moment * Fix other assert * Fix locker collisions * serializable sleeptime * Aether2D contacts * Physics is no longer crashing (and burning) * Add to the TODO list Co-authored-by: Metal Gear Sloth <metalgearsloth@gmail.com>
299 lines
11 KiB
C#
299 lines
11 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Robust.Client.Graphics;
|
|
using Robust.Client.Input;
|
|
using Robust.Client.ResourceManagement;
|
|
using Robust.Shared;
|
|
using Robust.Shared.Configuration;
|
|
using Robust.Shared.GameObjects;
|
|
using Robust.Shared.IoC;
|
|
using Robust.Shared.Maths;
|
|
using Robust.Shared.Physics;
|
|
using Robust.Shared.Physics.Broadphase;
|
|
using Robust.Shared.Prototypes;
|
|
|
|
namespace Robust.Client.Debugging
|
|
{
|
|
/// <inheritdoc />
|
|
public class DebugDrawing : IDebugDrawing
|
|
{
|
|
[Dependency] private readonly IOverlayManager _overlayManager = default!;
|
|
[Dependency] private readonly IComponentManager _componentManager = default!;
|
|
[Dependency] private readonly IEyeManager _eyeManager = default!;
|
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
|
[Dependency] private readonly IPhysicsManager _physicsManager = default!;
|
|
[Dependency] private readonly IEntityManager _entityManager = default!;
|
|
[Dependency] private readonly IInputManager _inputManager = default!;
|
|
|
|
private bool _debugColliders;
|
|
private bool _debugPositions;
|
|
|
|
/// <inheritdoc />
|
|
public bool DebugColliders
|
|
{
|
|
get => _debugColliders;
|
|
set
|
|
{
|
|
if (value == DebugColliders)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_debugColliders = value;
|
|
|
|
if (value)
|
|
{
|
|
_overlayManager.AddOverlay(new PhysicsOverlay(_componentManager, _eyeManager,
|
|
_prototypeManager, _inputManager, _physicsManager));
|
|
}
|
|
else
|
|
{
|
|
_overlayManager.RemoveOverlay(nameof(PhysicsOverlay));
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public bool DebugPositions
|
|
{
|
|
get => _debugPositions;
|
|
set
|
|
{
|
|
if (value == DebugPositions)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_debugPositions = value;
|
|
|
|
if (value)
|
|
{
|
|
_overlayManager.AddOverlay(new EntityPositionOverlay(_entityManager, _eyeManager));
|
|
}
|
|
else
|
|
{
|
|
_overlayManager.RemoveOverlay(nameof(EntityPositionOverlay));
|
|
}
|
|
}
|
|
}
|
|
|
|
private class PhysicsOverlay : Overlay
|
|
{
|
|
private readonly IComponentManager _componentManager;
|
|
private readonly IEyeManager _eyeManager;
|
|
private readonly IInputManager _inputManager;
|
|
private readonly IPhysicsManager _physicsManager;
|
|
|
|
public override OverlaySpace Space => OverlaySpace.WorldSpace | OverlaySpace.ScreenSpace;
|
|
private readonly ShaderInstance _shader;
|
|
private readonly Font _font;
|
|
|
|
private Vector2 _hoverStartScreen = Vector2.Zero;
|
|
private List<IPhysBody> _hoverBodies = new();
|
|
|
|
public PhysicsOverlay(IComponentManager compMan, IEyeManager eyeMan, IPrototypeManager protoMan, IInputManager inputManager, IPhysicsManager physicsManager)
|
|
: base(nameof(PhysicsOverlay))
|
|
{
|
|
_componentManager = compMan;
|
|
_eyeManager = eyeMan;
|
|
_inputManager = inputManager;
|
|
_physicsManager = physicsManager;
|
|
|
|
_shader = protoMan.Index<ShaderPrototype>("unshaded").Instance();
|
|
var cache = IoCManager.Resolve<IResourceCache>();
|
|
_font = new VectorFont(cache.GetResource<FontResource>("/Fonts/NotoSans/NotoSans-Regular.ttf"), 10);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
protected override void Draw(DrawingHandleBase handle, OverlaySpace currentSpace)
|
|
{
|
|
switch (currentSpace)
|
|
{
|
|
case OverlaySpace.ScreenSpace:
|
|
DrawScreen((DrawingHandleScreen) handle);
|
|
break;
|
|
case OverlaySpace.WorldSpace:
|
|
DrawWorld((DrawingHandleWorld) handle);
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
private void DrawScreen(DrawingHandleScreen screenHandle)
|
|
{
|
|
var lineHeight = _font.GetLineHeight(1f);
|
|
Vector2 drawPos = _hoverStartScreen + new Vector2(20, 0) + new Vector2(0, -(_hoverBodies.Count * 4 * lineHeight / 2f));
|
|
int row = 0;
|
|
|
|
foreach (var body in _hoverBodies)
|
|
{
|
|
if (body != _hoverBodies[0])
|
|
{
|
|
DrawString(screenHandle, _font, drawPos + new Vector2(0, row * lineHeight), "------");
|
|
row++;
|
|
}
|
|
|
|
DrawString(screenHandle, _font, drawPos + new Vector2(0, row * lineHeight), $"Ent: {body.Entity}");
|
|
row++;
|
|
DrawString(screenHandle, _font, drawPos + new Vector2(0, row * lineHeight), $"Layer: {Convert.ToString(body.CollisionLayer, 2)}");
|
|
row++;
|
|
DrawString(screenHandle, _font, drawPos + new Vector2(0, row * lineHeight), $"Mask: {Convert.ToString(body.CollisionMask, 2)}");
|
|
row++;
|
|
DrawString(screenHandle, _font, drawPos + new Vector2(0, row * lineHeight), $"Enabled: {body.CanCollide}, Hard: {body.Hard}, Anchored: {(body).BodyType == BodyType.Static}");
|
|
row++;
|
|
}
|
|
|
|
}
|
|
|
|
private void DrawWorld(DrawingHandleWorld worldHandle)
|
|
{
|
|
worldHandle.UseShader(_shader);
|
|
var drawing = new PhysDrawingAdapter(worldHandle);
|
|
|
|
_hoverBodies.Clear();
|
|
var mouseScreenPos = _inputManager.MouseScreenPosition;
|
|
var mouseWorldPos = _eyeManager.ScreenToMap(mouseScreenPos).Position;
|
|
_hoverStartScreen = mouseScreenPos;
|
|
|
|
var viewport = _eyeManager.GetWorldViewport();
|
|
|
|
if (viewport.IsEmpty()) return;
|
|
|
|
var mapId = _eyeManager.CurrentMap;
|
|
|
|
foreach (var physBody in EntitySystem.Get<SharedBroadPhaseSystem>().GetCollidingEntities(mapId, viewport))
|
|
{
|
|
// all entities have a TransformComponent
|
|
var transform = physBody.Entity.Transform;
|
|
|
|
var worldBox = physBody.GetWorldAABB();
|
|
if (worldBox.IsEmpty()) continue;
|
|
|
|
var colorEdge = Color.Red.WithAlpha(0.33f);
|
|
var sleepThreshold = IoCManager.Resolve<IConfigurationManager>().GetCVar(CVars.TimeToSleep);
|
|
|
|
foreach (var fixture in physBody.Fixtures)
|
|
{
|
|
var shape = fixture.Shape;
|
|
var sleepPercent = physBody.Awake ? physBody.SleepTime / sleepThreshold : 1.0f;
|
|
shape.DebugDraw(drawing, transform.WorldMatrix, in viewport, sleepPercent);
|
|
}
|
|
|
|
if (worldBox.Contains(mouseWorldPos))
|
|
{
|
|
_hoverBodies.Add(physBody);
|
|
}
|
|
|
|
// draw AABB
|
|
worldHandle.DrawRect(worldBox, colorEdge, false);
|
|
}
|
|
}
|
|
|
|
private static void DrawString(DrawingHandleScreen handle, Font font, Vector2 pos, string str)
|
|
{
|
|
var baseLine = new Vector2(pos.X, font.GetAscent(1) + pos.Y);
|
|
|
|
foreach (var chr in str)
|
|
{
|
|
var advance = font.DrawChar(handle, chr, baseLine, 1, Color.White);
|
|
baseLine += new Vector2(advance, 0);
|
|
}
|
|
}
|
|
|
|
private class PhysDrawingAdapter : DebugDrawingHandle
|
|
{
|
|
private readonly DrawingHandleWorld _handle;
|
|
|
|
public PhysDrawingAdapter(DrawingHandleWorld worldHandle)
|
|
{
|
|
_handle = worldHandle;
|
|
}
|
|
|
|
public override Color WakeMixColor => Color.White;
|
|
public override Color GridFillColor => Color.Blue.WithAlpha(0.05f);
|
|
public override Color RectFillColor => Color.Green.WithAlpha(0.25f);
|
|
|
|
public override Color CalcWakeColor(Color color, float wakePercent)
|
|
{
|
|
var percent = MathHelper.Clamp(wakePercent, 0, 1);
|
|
|
|
var r = 1 - (percent * (1 - color.R));
|
|
var g = 1 - (percent * (1 - color.G));
|
|
var b = 1 - (percent * (1 - color.B));
|
|
|
|
return new Color(r, g, b, color.A);
|
|
}
|
|
|
|
public override void DrawRect(in Box2 box, in Color color)
|
|
{
|
|
_handle.DrawRect(box, color);
|
|
}
|
|
|
|
public override void DrawRect(in Box2Rotated box, in Color color)
|
|
{
|
|
_handle.DrawRect(box, color);
|
|
}
|
|
|
|
public override void DrawCircle(Vector2 origin, float radius, in Color color)
|
|
{
|
|
_handle.DrawCircle(origin, radius, color);
|
|
}
|
|
|
|
public override void DrawPolygonShape(Vector2[] vertices, in Color color)
|
|
{
|
|
_handle.DrawPrimitives(DrawPrimitiveTopology.TriangleFan, vertices, color);
|
|
}
|
|
|
|
public override void DrawLine(Vector2 start, Vector2 end, in Color color)
|
|
{
|
|
_handle.DrawLine(start, end, color);
|
|
}
|
|
|
|
public override void SetTransform(in Matrix3 transform)
|
|
{
|
|
_handle.SetTransform(transform);
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
|
|
private sealed class EntityPositionOverlay : Overlay
|
|
{
|
|
private readonly IEntityManager _entityManager;
|
|
private readonly IEyeManager _eyeManager;
|
|
|
|
public override OverlaySpace Space => OverlaySpace.WorldSpace;
|
|
|
|
public EntityPositionOverlay(IEntityManager entityManager, IEyeManager eyeManager) : base(nameof(EntityPositionOverlay))
|
|
{
|
|
_entityManager = entityManager;
|
|
_eyeManager = eyeManager;
|
|
}
|
|
|
|
protected override void Draw(DrawingHandleBase handle, OverlaySpace currentSpace)
|
|
{
|
|
const float stubLength = 0.25f;
|
|
|
|
var worldHandle = (DrawingHandleWorld) handle;
|
|
foreach (var entity in _entityManager.GetEntities())
|
|
{
|
|
var transform = entity.Transform;
|
|
if (transform.MapID != _eyeManager.CurrentMap ||
|
|
!_eyeManager.GetWorldViewport().Contains(transform.WorldPosition))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var center = transform.WorldPosition;
|
|
var xLine = transform.WorldRotation.RotateVec(Vector2.UnitX);
|
|
var yLine = transform.WorldRotation.RotateVec(Vector2.UnitY);
|
|
|
|
worldHandle.DrawLine(center, center + xLine * stubLength, Color.Red);
|
|
worldHandle.DrawLine(center, center + yLine * stubLength, Color.Green);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|