mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-15 03:30:53 +01:00
Revert "Move physics fixtures to its own component (#2220)"
This reverts commit ebc0fc9c60.
This commit is contained in:
@@ -130,7 +130,7 @@ namespace Robust.Server.Console.Commands
|
||||
Hard = true
|
||||
};
|
||||
|
||||
var broadphase = EntitySystem.Get<FixtureSystem>();
|
||||
var broadphase = EntitySystem.Get<SharedBroadphaseSystem>();
|
||||
|
||||
broadphase.CreateFixture(ground, horizontalFixture);
|
||||
|
||||
@@ -194,7 +194,7 @@ namespace Robust.Server.Console.Commands
|
||||
Hard = true
|
||||
};
|
||||
|
||||
var broadphase = EntitySystem.Get<FixtureSystem>();
|
||||
var broadphase = EntitySystem.Get<SharedBroadphaseSystem>();
|
||||
broadphase.CreateFixture(ground, horizontalFixture);
|
||||
|
||||
var vertical = new EdgeShape(new Vector2(10, 0), new Vector2(10, 10));
|
||||
@@ -258,7 +258,7 @@ namespace Robust.Server.Console.Commands
|
||||
Hard = true
|
||||
};
|
||||
|
||||
var broadphase = EntitySystem.Get<FixtureSystem>();
|
||||
var broadphase = EntitySystem.Get<SharedBroadphaseSystem>();
|
||||
broadphase.CreateFixture(ground, horizontalFixture);
|
||||
|
||||
// Setup boxes
|
||||
@@ -296,7 +296,7 @@ namespace Robust.Server.Console.Commands
|
||||
|
||||
private void CreateTumbler(MapId mapId)
|
||||
{
|
||||
var broadphaseSystem = EntitySystem.Get<FixtureSystem>();
|
||||
var broadphaseSystem = EntitySystem.Get<SharedBroadphaseSystem>();
|
||||
var entityManager = IoCManager.Resolve<IEntityManager>();
|
||||
|
||||
var groundUid = entityManager.SpawnEntity(null, new MapCoordinates(0f, 0f, mapId)).Uid;
|
||||
|
||||
@@ -51,11 +51,11 @@ namespace Robust.Server.Map
|
||||
|
||||
// TODO: Like MapManager injecting this is a PITA so need to work out an easy way to do it.
|
||||
// Maybe just add like a PostInject method that gets called way later?
|
||||
var fixtureSystem = EntitySystem.Get<FixtureSystem>();
|
||||
var broadphaseSystem = EntitySystem.Get<SharedBroadphaseSystem>();
|
||||
|
||||
foreach (var fixture in chunk.Fixtures)
|
||||
{
|
||||
fixtureSystem.DestroyFixture(body, fixture);
|
||||
broadphaseSystem.DestroyFixture(body, fixture);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -441,21 +441,19 @@ namespace Robust.Server.Maps
|
||||
{
|
||||
var entManager = IoCManager.Resolve<IEntityManager>();
|
||||
var gridFixtures = EntitySystem.Get<GridFixtureSystem>();
|
||||
var fixtureSystem = EntitySystem.Get<FixtureSystem>();
|
||||
var broadphaseSystem = EntitySystem.Get<SharedBroadphaseSystem>();
|
||||
|
||||
foreach (var grid in Grids)
|
||||
{
|
||||
var gridInternal = (IMapGridInternal) grid;
|
||||
var body = entManager.EnsureComponent<PhysicsComponent>(grid.GridEntityId);
|
||||
body.Broadphase = _mapManager.GetMapEntity(grid.ParentMapId).GetComponent<BroadphaseComponent>();
|
||||
var fixtures = entManager.EnsureComponent<FixturesComponent>(grid.GridEntityId);
|
||||
var body = entManager.EnsureComponent<PhysicsComponent>(entManager.GetEntity(grid.GridEntityId));
|
||||
gridFixtures.ProcessGrid(gridInternal);
|
||||
|
||||
// Need to go through and double-check we don't have any hanging-on fixtures that
|
||||
// no longer apply (e.g. due to an update in GridFixtureSystem)
|
||||
var toRemove = new RemQueue<Fixture>();
|
||||
var toRemove = new List<Fixture>();
|
||||
|
||||
foreach (var (_, fixture) in fixtures.Fixtures)
|
||||
foreach (var fixture in body.Fixtures)
|
||||
{
|
||||
var found = false;
|
||||
|
||||
@@ -479,10 +477,8 @@ namespace Robust.Server.Maps
|
||||
|
||||
foreach (var fixture in toRemove)
|
||||
{
|
||||
fixtureSystem.DestroyFixture(body, fixture, false, fixtures);
|
||||
broadphaseSystem.DestroyFixture(fixture);
|
||||
}
|
||||
|
||||
fixtureSystem.FixtureUpdate(fixtures, body);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,4 +24,17 @@ namespace Robust.Shared.GameObjects
|
||||
Component = component;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class FixtureUpdateMessage : EntityEventArgs
|
||||
{
|
||||
public PhysicsComponent Body { get; }
|
||||
|
||||
public Fixture Fixture { get; }
|
||||
|
||||
public FixtureUpdateMessage(PhysicsComponent body, Fixture fixture)
|
||||
{
|
||||
Body = body;
|
||||
Fixture = fixture;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,9 +28,13 @@ using System.Linq;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Physics.Broadphase;
|
||||
using Robust.Shared.Physics.Collision.Shapes;
|
||||
using Robust.Shared.Physics.Dynamics;
|
||||
using Robust.Shared.Physics.Dynamics.Contacts;
|
||||
using Robust.Shared.Players;
|
||||
@@ -73,13 +77,6 @@ namespace Robust.Shared.GameObjects
|
||||
|
||||
public bool IgnoreCCD { get; set; }
|
||||
|
||||
// TODO: Placeholder; look it's disgusting but my main concern is stopping fixtures being serialized every tick
|
||||
// on physics bodies for massive shuttle perf savings.
|
||||
[Obsolete("Use FixturesComponent instead.")]
|
||||
public IReadOnlyList<Fixture> Fixtures => Owner.EntityManager.GetComponent<FixturesComponent>(OwnerUid).Fixtures.Values.ToList();
|
||||
|
||||
public int FixtureCount => Owner.EntityManager.GetComponent<FixturesComponent>(OwnerUid).Fixtures.Count;
|
||||
|
||||
[ViewVariables]
|
||||
public int ContactCount
|
||||
{
|
||||
@@ -97,6 +94,47 @@ namespace Robust.Shared.GameObjects
|
||||
}
|
||||
}
|
||||
|
||||
[ViewVariables]
|
||||
public Box2 LocalAABB
|
||||
{
|
||||
get
|
||||
{
|
||||
var broadphaseSystem = EntitySystem.Get<SharedBroadphaseSystem>();
|
||||
var broadphase = broadphaseSystem.GetBroadphase(this);
|
||||
|
||||
if (broadphase == null) return new Box2();
|
||||
|
||||
var worldPos = Owner.Transform.WorldPosition;
|
||||
var aabb = new Box2(worldPos, worldPos);
|
||||
|
||||
foreach (var fixture in Fixtures)
|
||||
{
|
||||
foreach (var proxy in fixture.Proxies)
|
||||
{
|
||||
aabb = aabb.Union(proxy.AABB);
|
||||
}
|
||||
}
|
||||
|
||||
return aabb;
|
||||
}
|
||||
}
|
||||
|
||||
[ViewVariables]
|
||||
public Box2 WorldAABB
|
||||
{
|
||||
get
|
||||
{
|
||||
var broadphaseSystem = EntitySystem.Get<SharedBroadphaseSystem>();
|
||||
var broadphase = broadphaseSystem.GetBroadphase(this);
|
||||
|
||||
if (broadphase == null) return new Box2();
|
||||
var localAABB = LocalAABB;
|
||||
var center = broadphase.Owner.Transform.WorldMatrix.Transform(localAABB.Center);
|
||||
|
||||
return new Box2Rotated(localAABB.Translated(center), broadphase.Owner.Transform.WorldRotation, center).CalcBoundingBox();
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<Contact> Contacts
|
||||
{
|
||||
get
|
||||
@@ -256,10 +294,29 @@ namespace Robust.Shared.GameObjects
|
||||
Awake = true;
|
||||
}
|
||||
|
||||
void ISerializationHooks.AfterDeserialization()
|
||||
{
|
||||
FixtureCount = _fixtures.Count;
|
||||
|
||||
foreach (var fixture in _fixtures)
|
||||
{
|
||||
fixture.Body = this;
|
||||
fixture.ComputeProperties();
|
||||
fixture.ID = GetFixtureName(fixture);
|
||||
}
|
||||
|
||||
ResetMassData();
|
||||
|
||||
if (_mass > 0f && (BodyType & (BodyType.Dynamic | BodyType.KinematicController)) != 0)
|
||||
{
|
||||
_invMass = 1.0f / _mass;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override ComponentState GetComponentState()
|
||||
{
|
||||
return new PhysicsComponentState(_canCollide, _sleepingAllowed, _fixedRotation, _bodyStatus, _linVelocity, _angVelocity, _bodyType);
|
||||
return new PhysicsComponentState(_canCollide, _sleepingAllowed, _fixedRotation, _bodyStatus, _fixtures, LinearVelocity, AngularVelocity, BodyType);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -276,7 +333,95 @@ namespace Robust.Shared.GameObjects
|
||||
// So transform doesn't apply MapId in the HandleComponentState because ??? so MapId can still be 0.
|
||||
// Fucking kill me, please. You have no idea deep the rabbit hole of shitcode goes to make this work.
|
||||
|
||||
/*
|
||||
* -- Fixtures --
|
||||
*/
|
||||
|
||||
var toAddFixtures = new List<Fixture>();
|
||||
var toRemoveFixtures = new List<Fixture>();
|
||||
var computeProperties = false;
|
||||
|
||||
// Given a bunch of data isn't serialized need to sort of re-initialise it
|
||||
var newFixtures = new List<Fixture>(newState.Fixtures.Count);
|
||||
foreach (var fixture in newState.Fixtures)
|
||||
{
|
||||
var newFixture = new Fixture();
|
||||
fixture.CopyTo(newFixture);
|
||||
newFixture.Body = this;
|
||||
newFixtures.Add(newFixture);
|
||||
}
|
||||
|
||||
// Add / update new fixtures
|
||||
foreach (var fixture in newFixtures)
|
||||
{
|
||||
var found = false;
|
||||
|
||||
foreach (var existing in _fixtures)
|
||||
{
|
||||
if (!fixture.ID.Equals(existing.ID)) continue;
|
||||
|
||||
if (!fixture.Equals(existing))
|
||||
{
|
||||
toAddFixtures.Add(fixture);
|
||||
toRemoveFixtures.Add(existing);
|
||||
}
|
||||
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
toAddFixtures.Add(fixture);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove old fixtures
|
||||
foreach (var existing in _fixtures)
|
||||
{
|
||||
var found = false;
|
||||
|
||||
foreach (var fixture in newFixtures)
|
||||
{
|
||||
if (fixture.ID.Equals(existing.ID))
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
toRemoveFixtures.Add(existing);
|
||||
}
|
||||
}
|
||||
|
||||
var broadphaseSystem = EntitySystem.Get<SharedBroadphaseSystem>();
|
||||
|
||||
foreach (var fixture in toRemoveFixtures)
|
||||
{
|
||||
computeProperties = true;
|
||||
broadphaseSystem.DestroyFixture(this, fixture);
|
||||
}
|
||||
|
||||
// TODO: We also still need event listeners for shapes (Probably need C# events)
|
||||
foreach (var fixture in toAddFixtures)
|
||||
{
|
||||
computeProperties = true;
|
||||
broadphaseSystem.CreateFixture(this, fixture);
|
||||
fixture.Shape.ApplyState();
|
||||
}
|
||||
|
||||
/*
|
||||
* -- Sundries --
|
||||
*/
|
||||
|
||||
Dirty();
|
||||
if (computeProperties)
|
||||
{
|
||||
ResetMassData();
|
||||
}
|
||||
|
||||
LinearVelocity = newState.LinearVelocity;
|
||||
// Logger.Debug($"{IGameTiming.TickStampStatic}: [{Owner}] {LinearVelocity}");
|
||||
AngularVelocity = newState.AngularVelocity;
|
||||
@@ -284,6 +429,24 @@ namespace Robust.Shared.GameObjects
|
||||
Predict = false;
|
||||
}
|
||||
|
||||
public Fixture? GetFixture(string name)
|
||||
{
|
||||
// Sooo I'd rather have fixtures as a list in serialization but there's not really an easy way to have it as a
|
||||
// temporary value on deserialization so we can store it as a dictionary of <name, fixture>
|
||||
// given 100% of bodies have 1-2 fixtures this isn't really a performance problem right now but
|
||||
// should probably be done at some stage
|
||||
// If we really need it then you just deserialize onto a dummy field that then just never gets used again.
|
||||
foreach (var fixture in _fixtures)
|
||||
{
|
||||
if (fixture.ID.Equals(name))
|
||||
{
|
||||
return fixture;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the dynamics of this body.
|
||||
/// Sets torque, force and linear/angular velocity to 0
|
||||
@@ -305,7 +468,7 @@ namespace Robust.Shared.GameObjects
|
||||
|
||||
var bounds = new Box2(transform.Position, transform.Position);
|
||||
|
||||
foreach (var fixture in Fixtures)
|
||||
foreach (var fixture in _fixtures)
|
||||
{
|
||||
for (var i = 0; i < fixture.Shape.ChildCount; i++)
|
||||
{
|
||||
@@ -317,6 +480,17 @@ namespace Robust.Shared.GameObjects
|
||||
return bounds;
|
||||
}
|
||||
|
||||
[ViewVariables]
|
||||
public int FixtureCount { get; internal set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
[ViewVariables]
|
||||
public IReadOnlyList<Fixture> Fixtures => _fixtures;
|
||||
|
||||
[DataField("fixtures")]
|
||||
[NeverPushInheritance]
|
||||
internal List<Fixture> _fixtures = new();
|
||||
|
||||
/// <summary>
|
||||
/// Enables or disabled collision processing of this component.
|
||||
/// </summary>
|
||||
@@ -351,19 +525,57 @@ namespace Robust.Shared.GameObjects
|
||||
/// This is useful for triggers or such to detect collision without actually causing a blockage.
|
||||
/// </remarks>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public bool Hard { get; internal set; }
|
||||
public bool Hard
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (var fixture in Fixtures)
|
||||
{
|
||||
if (fixture.Hard) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
set
|
||||
{
|
||||
foreach (var fixture in Fixtures)
|
||||
{
|
||||
fixture.Hard = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bitmask of the collision layers this component is a part of.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public int CollisionLayer { get; internal set; }
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public int CollisionLayer
|
||||
{
|
||||
get
|
||||
{
|
||||
var layers = 0x0;
|
||||
|
||||
foreach (var fixture in Fixtures)
|
||||
layers |= fixture.CollisionLayer;
|
||||
return layers;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bitmask of the layers this component collides with.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public int CollisionMask { get; internal set; }
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public int CollisionMask
|
||||
{
|
||||
get
|
||||
{
|
||||
var mask = 0x0;
|
||||
|
||||
foreach (var fixture in Fixtures)
|
||||
mask |= fixture.CollisionMask;
|
||||
return mask;
|
||||
}
|
||||
}
|
||||
|
||||
// I made Mass read-only just because overwriting it doesn't touch inertia.
|
||||
/// <summary>
|
||||
@@ -761,6 +973,41 @@ namespace Robust.Shared.GameObjects
|
||||
return Transform.MulT(new Quaternion2D((float) Owner.EntityManager.GetComponent<TransformComponent>(OwnerUid).WorldRotation.Theta), worldVector);
|
||||
}
|
||||
|
||||
public void FixtureChanged(Fixture fixture)
|
||||
{
|
||||
// TODO: Optimise this a LOT
|
||||
Dirty();
|
||||
Owner.EntityManager.EventBus.RaiseEvent(EventSource.Local, new FixtureUpdateMessage(this, fixture));
|
||||
}
|
||||
|
||||
public string GetFixtureName(Fixture fixture)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(fixture.ID)) return fixture.ID;
|
||||
|
||||
var i = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
var found = false;
|
||||
++i;
|
||||
var name = $"fixture_{i}";
|
||||
|
||||
foreach (var existing in _fixtures)
|
||||
{
|
||||
if (existing.ID.Equals(name))
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
return name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Transform GetTransform()
|
||||
{
|
||||
var (worldPos, worldRot) = Owner.Transform.GetWorldPositionRotation();
|
||||
@@ -874,11 +1121,16 @@ namespace Robust.Shared.GameObjects
|
||||
{
|
||||
_awake = false;
|
||||
}
|
||||
}
|
||||
|
||||
var startup = new PhysicsInitializedEvent(Owner.Uid);
|
||||
Owner.EntityManager.EventBus.RaiseLocalEvent(Owner.Uid, ref startup);
|
||||
|
||||
ResetMassData();
|
||||
protected override void OnRemove()
|
||||
{
|
||||
base.OnRemove();
|
||||
// Need to do these immediately in case collision behaviors deleted the body
|
||||
// TODO: Could be more optimal as currently broadphase will call this ANYWAY
|
||||
DestroyContacts();
|
||||
EntitySystem.Get<SharedBroadphaseSystem>().RemoveBody(this);
|
||||
CanCollide = false;
|
||||
}
|
||||
|
||||
public void ResetMassData()
|
||||
@@ -895,9 +1147,9 @@ namespace Robust.Shared.GameObjects
|
||||
}
|
||||
|
||||
var localCenter = Vector2.Zero;
|
||||
var shapeManager = EntitySystem.Get<FixtureSystem>();
|
||||
var shapeManager = IoCManager.Resolve<IShapeManager>();
|
||||
|
||||
foreach (var fixture in Fixtures)
|
||||
foreach (var fixture in _fixtures)
|
||||
{
|
||||
if (fixture.Mass <= 0.0f) continue;
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ namespace Robust.Shared.GameObjects
|
||||
public readonly bool SleepingAllowed;
|
||||
public readonly bool FixedRotation;
|
||||
public readonly BodyStatus Status;
|
||||
public readonly List<Fixture> Fixtures;
|
||||
|
||||
public readonly Vector2 LinearVelocity;
|
||||
public readonly float AngularVelocity;
|
||||
@@ -27,6 +28,8 @@ namespace Robust.Shared.GameObjects
|
||||
/// <param name="sleepingAllowed"></param>
|
||||
/// <param name="fixedRotation"></param>
|
||||
/// <param name="status"></param>
|
||||
/// <param name="fixtures"></param>
|
||||
/// <param name="joints"></param>
|
||||
/// <param name="linearVelocity">Current linear velocity of the entity in meters per second.</param>
|
||||
/// <param name="angularVelocity">Current angular velocity of the entity in radians per sec.</param>
|
||||
/// <param name="bodyType"></param>
|
||||
@@ -35,6 +38,7 @@ namespace Robust.Shared.GameObjects
|
||||
bool sleepingAllowed,
|
||||
bool fixedRotation,
|
||||
BodyStatus status,
|
||||
List<Fixture> fixtures,
|
||||
Vector2 linearVelocity,
|
||||
float angularVelocity,
|
||||
BodyType bodyType)
|
||||
@@ -43,6 +47,7 @@ namespace Robust.Shared.GameObjects
|
||||
SleepingAllowed = sleepingAllowed;
|
||||
FixedRotation = fixedRotation;
|
||||
Status = status;
|
||||
Fixtures = fixtures;
|
||||
|
||||
LinearVelocity = linearVelocity;
|
||||
AngularVelocity = angularVelocity;
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
namespace Robust.Shared.GameObjects
|
||||
{
|
||||
public readonly struct PhysicsInitializedEvent
|
||||
{
|
||||
public readonly EntityUid Uid;
|
||||
|
||||
public PhysicsInitializedEvent(EntityUid uid)
|
||||
{
|
||||
Uid = uid;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@ namespace Robust.Shared.GameObjects
|
||||
public abstract class SharedGridFixtureSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
[Dependency] private readonly FixtureSystem _fixtures = default!;
|
||||
[Dependency] private readonly SharedBroadphaseSystem _broadphase = default!;
|
||||
|
||||
private bool _enabled;
|
||||
|
||||
@@ -59,12 +59,6 @@ namespace Robust.Shared.GameObjects
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gridEnt.TryGetComponent(out FixturesComponent? fixturesComponent))
|
||||
{
|
||||
Logger.ErrorS("physics", $"Trying to regenerate collision for {gridEnt} that doesn't have {nameof(fixturesComponent)}");
|
||||
return;
|
||||
}
|
||||
|
||||
var origin = chunk.Indices * chunk.ChunkSize;
|
||||
|
||||
// So we store a reference to the fixture on the chunk because it's easier to cross-reference it.
|
||||
@@ -129,7 +123,7 @@ namespace Robust.Shared.GameObjects
|
||||
foreach (var fixture in toRemove)
|
||||
{
|
||||
chunk.Fixtures.Remove(fixture);
|
||||
_fixtures.DestroyFixture(fixture, false, fixturesComponent);
|
||||
_broadphase.DestroyFixture(fixture);
|
||||
}
|
||||
|
||||
if (newFixtures.Count > 0 || toRemove.List?.Count > 0)
|
||||
@@ -140,7 +134,7 @@ namespace Robust.Shared.GameObjects
|
||||
// Anything remaining is a new fixture (or at least, may have not serialized onto the chunk yet).
|
||||
foreach (var fixture in newFixtures)
|
||||
{
|
||||
var existingFixture = _fixtures.GetFixtureOrNull(physicsComponent, fixture.ID);
|
||||
var existingFixture = physicsComponent.GetFixture(fixture.ID);
|
||||
// Check if it's the same (otherwise remove anyway).
|
||||
if (existingFixture?.Shape is PolygonShape poly &&
|
||||
poly.EqualsApprox((PolygonShape) fixture.Shape))
|
||||
@@ -150,14 +144,11 @@ namespace Robust.Shared.GameObjects
|
||||
}
|
||||
|
||||
chunk.Fixtures.Add(fixture);
|
||||
_fixtures.CreateFixture(physicsComponent, fixture, false, fixturesComponent);
|
||||
_broadphase.CreateFixture(physicsComponent, fixture);
|
||||
}
|
||||
|
||||
if (updated)
|
||||
{
|
||||
_fixtures.FixtureUpdate(fixturesComponent, physicsComponent);
|
||||
EntityManager.EventBus.RaiseLocalEvent(gridEnt.Uid,new GridFixtureChangeEvent {NewFixtures = chunk.Fixtures});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace Robust.Shared.GameObjects
|
||||
|
||||
var state = (body, entities);
|
||||
|
||||
foreach (var fixture in body.Fixtures)
|
||||
foreach (var fixture in body._fixtures)
|
||||
{
|
||||
foreach (var proxy in fixture.Proxies)
|
||||
{
|
||||
@@ -165,7 +165,7 @@ namespace Robust.Shared.GameObjects
|
||||
|
||||
var localTransform = new Transform(broadInvMatrix.Transform(transform.Position), transform.Quaternion2D.Angle - broadRot);
|
||||
|
||||
foreach (var fixture in body.Fixtures)
|
||||
foreach (var fixture in body._fixtures)
|
||||
{
|
||||
var collisionMask = fixture.CollisionMask;
|
||||
var collisionLayer = fixture.CollisionLayer;
|
||||
|
||||
@@ -160,5 +160,10 @@ namespace Robust.Shared.Physics.Collision.Shapes
|
||||
// It's a line
|
||||
return 0f;
|
||||
}
|
||||
|
||||
public void ApplyState()
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,5 +39,7 @@ namespace Robust.Shared.Physics.Collision.Shapes
|
||||
/// Calculate the AABB of the shape.
|
||||
/// </summary>
|
||||
Box2 ComputeAABB(Transform transform, int childIndex);
|
||||
|
||||
void ApplyState();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ namespace Robust.Shared.Physics.Collision.Shapes
|
||||
{
|
||||
if (MathHelper.CloseToPercent(_radius, value)) return;
|
||||
_radius = value;
|
||||
OnDataChanged?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +58,7 @@ namespace Robust.Shared.Physics.Collision.Shapes
|
||||
return;
|
||||
|
||||
_localBounds = value;
|
||||
OnDataChanged?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,6 +77,13 @@ namespace Robust.Shared.Physics.Collision.Shapes
|
||||
return new Box2Rotated(_localBounds.Translated(transform.Position), transform.Quaternion2D.Angle, transform.Position).CalcBoundingBox().Enlarged(_radius);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ApplyState() { }
|
||||
|
||||
// TODO
|
||||
[field: NonSerialized]
|
||||
public event Action? OnDataChanged;
|
||||
|
||||
[Pure]
|
||||
internal List<Vector2> GetVertices()
|
||||
{
|
||||
|
||||
@@ -72,6 +72,9 @@ namespace Robust.Shared.Physics.Collision.Shapes
|
||||
return new Box2(p.X - _radius, p.Y - _radius, p.X + _radius, p.Y + _radius);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ApplyState() { }
|
||||
|
||||
public bool Equals(IPhysShape? other)
|
||||
{
|
||||
if (other is not PhysShapeCircle otherCircle) return false;
|
||||
|
||||
@@ -128,7 +128,9 @@ namespace Robust.Shared.Physics.Collision.Shapes
|
||||
Normals[i] = temp.Normalized;
|
||||
}
|
||||
|
||||
// TODO: Updates (network etc)
|
||||
// Compute the polygon mass data
|
||||
// TODO: Update fixture. Maybe use events for it? Who tf knows.
|
||||
// If we get grid polys then we'll actually need runtime updating of bbs.
|
||||
}
|
||||
|
||||
public ShapeType ShapeType => ShapeType.Polygon;
|
||||
@@ -245,6 +247,11 @@ namespace Robust.Shared.Physics.Collision.Shapes
|
||||
return new Box2(lower - r, upper + r);
|
||||
}
|
||||
|
||||
public void ApplyState()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
public static explicit operator PolygonShape(PhysShapeAabb aabb)
|
||||
{
|
||||
// TODO: Need a test for this probably, if there is no AABB manifold generator done at least.
|
||||
|
||||
@@ -82,8 +82,7 @@ namespace Robust.Shared.Physics.Dynamics
|
||||
if (MathHelper.CloseToPercent(value, _friction)) return;
|
||||
|
||||
_friction = value;
|
||||
// TODO: EntitySystem
|
||||
// Body.FixtureChanged(this);
|
||||
Body.FixtureChanged(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,11 +99,10 @@ namespace Robust.Shared.Physics.Dynamics
|
||||
get => _restitution;
|
||||
set
|
||||
{
|
||||
if (MathHelper.CloseTo(value, _restitution)) return;
|
||||
if (MathHelper.CloseToPercent(value, _restitution)) return;
|
||||
|
||||
// TODO: EntitySystem
|
||||
_restitution = value;
|
||||
// Body.FixtureChanged(this);
|
||||
Body.FixtureChanged(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,10 +125,9 @@ namespace Robust.Shared.Physics.Dynamics
|
||||
if (_hard == value)
|
||||
return;
|
||||
|
||||
// TODO: EntitySystem
|
||||
_hard = value;
|
||||
Body.Awake = true;
|
||||
// Body.FixtureChanged(this);
|
||||
Body.FixtureChanged(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,9 +153,9 @@ namespace Robust.Shared.Physics.Dynamics
|
||||
{
|
||||
if (MathHelper.CloseToPercent(value, _mass)) return;
|
||||
|
||||
// TODO: EntitySystem
|
||||
_mass = MathF.Max(0f, value);
|
||||
// Body.FixtureChanged(this);
|
||||
ComputeProperties();
|
||||
Body.FixtureChanged(this);
|
||||
Body.ResetMassData();
|
||||
}
|
||||
}
|
||||
@@ -178,9 +175,8 @@ namespace Robust.Shared.Physics.Dynamics
|
||||
if (_collisionLayer == value)
|
||||
return;
|
||||
|
||||
// TODO: EntitySystem
|
||||
_collisionLayer = value;
|
||||
// Body.FixtureChanged(this);
|
||||
Body.FixtureChanged(this);
|
||||
EntitySystem.Get<SharedBroadphaseSystem>().Refilter(this);
|
||||
}
|
||||
}
|
||||
@@ -200,9 +196,8 @@ namespace Robust.Shared.Physics.Dynamics
|
||||
if (_collisionMask == value)
|
||||
return;
|
||||
|
||||
// TODO: EntitySystem
|
||||
_collisionMask = value;
|
||||
// Body.FixtureChanged(this);
|
||||
Body.FixtureChanged(this);
|
||||
EntitySystem.Get<SharedBroadphaseSystem>().Refilter(this);
|
||||
}
|
||||
}
|
||||
@@ -281,8 +276,47 @@ namespace Robust.Shared.Physics.Dynamics
|
||||
fixture._mass = _mass;
|
||||
}
|
||||
|
||||
#region ComputeProperties
|
||||
// Moved from Shape because no MassData on Shape anymore (due to serv3 and physics ease-of-use etc etc.)
|
||||
internal void ComputeProperties()
|
||||
{
|
||||
switch (Shape)
|
||||
{
|
||||
case EdgeShape edge:
|
||||
ComputeEdge(edge);
|
||||
break;
|
||||
case PhysShapeAabb aabb:
|
||||
ComputeAABB(aabb);
|
||||
break;
|
||||
case PhysShapeCircle circle:
|
||||
ComputeCircle(circle);
|
||||
break;
|
||||
case PolygonShape poly:
|
||||
ComputePoly(poly, out _);
|
||||
break;
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
#region ComputeProperties
|
||||
private void ComputeAABB(PhysShapeAabb aabb)
|
||||
{
|
||||
var area = aabb.LocalBounds.Width * aabb.LocalBounds.Height;
|
||||
float I = 0.0f;
|
||||
|
||||
//The area is too small for the engine to handle.
|
||||
DebugTools.Assert(area > float.Epsilon);
|
||||
|
||||
// Total mass
|
||||
// TODO: Do we need this?
|
||||
var density = area > 0.0f ? Mass / area : 0.0f;
|
||||
|
||||
// Center of mass
|
||||
aabb.Centroid = Vector2.Zero;
|
||||
|
||||
// Inertia tensor relative to the local origin (point s).
|
||||
_inertia = density * I;
|
||||
}
|
||||
|
||||
private void ComputePoly(PolygonShape poly, out float area)
|
||||
{
|
||||
|
||||
@@ -1,410 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Physics.Collision.Shapes;
|
||||
using Robust.Shared.Physics.Dynamics;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Shared.Physics
|
||||
{
|
||||
/// <summary>
|
||||
/// Manages physics fixtures.
|
||||
/// </summary>
|
||||
public sealed partial class FixtureSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedBroadphaseSystem _broadphaseSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<FixturesComponent, ComponentInit>(OnInit);
|
||||
SubscribeLocalEvent<FixturesComponent, ComponentShutdown>(OnShutdown);
|
||||
SubscribeLocalEvent<FixturesComponent, ComponentGetState>(OnGetState);
|
||||
SubscribeLocalEvent<FixturesComponent, ComponentHandleState>(OnHandleState);
|
||||
|
||||
SubscribeLocalEvent<PhysicsInitializedEvent>(OnPhysicsInit);
|
||||
SubscribeLocalEvent<PhysicsComponent, ComponentShutdown>(OnPhysicsShutdown);
|
||||
}
|
||||
|
||||
private void OnShutdown(EntityUid uid, FixturesComponent component, ComponentShutdown args)
|
||||
{
|
||||
// TODO: Need a better solution to this because the only reason I don't throw is that allcomponents test
|
||||
// Yes it is actively making the game buggier but I would essentially double the size of this PR trying to fix it
|
||||
// my best solution rn is move the broadphase property onto FixturesComponent and then refactor
|
||||
// SharedBroadphaseSystem a LOT.
|
||||
if (!EntityManager.TryGetComponent(uid, out PhysicsComponent? body))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Can't just get physicscomp on shutdown as it may be touched completely independently.
|
||||
body.DestroyContacts();
|
||||
_broadphaseSystem.RemoveBody(body, component);
|
||||
body.CanCollide = false;
|
||||
}
|
||||
|
||||
private void OnInit(EntityUid uid, FixturesComponent component, ComponentInit args)
|
||||
{
|
||||
// Convert the serialized list to the dictionary format as it may not necessarily have an ID in YAML
|
||||
// (probably change this someday for perf reasons?)
|
||||
foreach (var fixture in component.SerializedFixtures)
|
||||
{
|
||||
fixture.ID = GetFixtureName(component, fixture);
|
||||
|
||||
if (component.Fixtures.TryAdd(fixture.ID, fixture)) continue;
|
||||
|
||||
Logger.DebugS("physics", $"Tried to deserialize fixture {fixture.ID} on {uid} which already exists.");
|
||||
}
|
||||
|
||||
component.SerializedFixtures.Clear();
|
||||
|
||||
if (component.Fixtures.Count <= 0 ||
|
||||
!EntityManager.TryGetComponent(uid, out PhysicsComponent? body) ||
|
||||
!EntityManager.TryGetComponent(uid, out TransformComponent? xform)) return;
|
||||
|
||||
// Ordering issues man
|
||||
var broadphase = _broadphaseSystem.GetBroadphase(body);
|
||||
body.Broadphase = broadphase;
|
||||
|
||||
if (broadphase != null)
|
||||
{
|
||||
var worldPos = xform.WorldPosition;
|
||||
var worldRot = xform.WorldRotation;
|
||||
|
||||
// Can't resolve in serialization so here we are.
|
||||
// TODO: Support for large body DynamicTrees (i.e. 1 proxy for the entire body)
|
||||
foreach (var (_, fixture) in component.Fixtures)
|
||||
{
|
||||
// It's possible that fixtures were added at some stage prior to this so we'll just check if they're on the broadphase
|
||||
if (fixture.ProxyCount > 0) continue;
|
||||
|
||||
fixture.Body = body;
|
||||
|
||||
_broadphaseSystem.CreateProxies(fixture, worldPos, worldRot, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure all the right stuff is set on the body
|
||||
FixtureUpdate(component);
|
||||
}
|
||||
|
||||
#region Public
|
||||
|
||||
public void CreateFixture(PhysicsComponent body, Fixture fixture, bool updates = true, FixturesComponent? manager = null, TransformComponent? xform = null)
|
||||
{
|
||||
if (!Resolve(body.OwnerUid, ref manager, ref xform))
|
||||
{
|
||||
DebugTools.Assert(false);
|
||||
return;
|
||||
}
|
||||
|
||||
fixture.ID = GetFixtureName(manager, fixture);
|
||||
manager.Fixtures.Add(fixture.ID, fixture);
|
||||
fixture.Body = body;
|
||||
|
||||
// TODO: Assert world locked
|
||||
// Broadphase should be set in the future TM
|
||||
// Should only happen for nullspace / initializing entities
|
||||
if (body.Broadphase != null)
|
||||
{
|
||||
var worldPos = xform.WorldPosition;
|
||||
var worldRot = xform.WorldRotation;
|
||||
|
||||
_broadphaseSystem.UpdateBroadphaseCache(body.Broadphase);
|
||||
_broadphaseSystem.CreateProxies(fixture, worldPos, worldRot, false);
|
||||
}
|
||||
|
||||
// Supposed to be wrapped in density but eh
|
||||
if (updates)
|
||||
{
|
||||
FixtureUpdate(manager, body);
|
||||
body.ResetMassData();
|
||||
manager.Dirty();
|
||||
}
|
||||
// TODO: Set newcontacts to true.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="Fixture"/> from this shape and adds it to the specified <see cref="PhysicsComponent"/>
|
||||
/// </summary>
|
||||
public Fixture CreateFixture(PhysicsComponent body, IPhysShape shape)
|
||||
{
|
||||
var fixture = new Fixture(body, shape);
|
||||
CreateFixture(body, fixture);
|
||||
return fixture;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="Fixture"/> from this shape and adds it to the specified <see cref="PhysicsComponent"/> with mass.
|
||||
/// </summary>
|
||||
public void CreateFixture(PhysicsComponent body, IPhysShape shape, float mass)
|
||||
{
|
||||
// TODO: Make it take in density instead?
|
||||
var fixture = new Fixture(body, shape) {Mass = mass};
|
||||
CreateFixture(body, fixture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to get the <see cref="Fixture"/> with the specified ID for this body.
|
||||
/// </summary>
|
||||
public Fixture? GetFixtureOrNull(PhysicsComponent body, string id, FixturesComponent? manager = null)
|
||||
{
|
||||
if (!Resolve(body.OwnerUid, ref manager))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return manager.Fixtures.TryGetValue(id, out var fixture) ? fixture : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destroys the specified <see cref="Fixture"/> attached to the body.
|
||||
/// </summary>
|
||||
/// <param name="body">The specified body</param>
|
||||
/// <param name="id">The fixture ID</param>
|
||||
/// <param name="updates">Whether to update mass etc. Set false if you're doing a bulk operation</param>
|
||||
public void DestroyFixture(PhysicsComponent body, string id, bool updates = true)
|
||||
{
|
||||
var fixture = GetFixtureOrNull(body, id);
|
||||
|
||||
if (fixture == null) return;
|
||||
|
||||
DestroyFixture(body, fixture, updates);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destroys the specified <see cref="Fixture"/>
|
||||
/// </summary>
|
||||
/// <param name="fixture">The specified fixture</param>
|
||||
/// <param name="updates">Whether to update mass etc. Set false if you're doing a bulk operation</param>
|
||||
public void DestroyFixture(Fixture fixture, bool updates = true, FixturesComponent? manager = null)
|
||||
{
|
||||
DestroyFixture(fixture.Body, fixture, updates, manager);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destroys the specified <see cref="Fixture"/>
|
||||
/// </summary>
|
||||
/// <param name="updates">Whether to update mass etc. Set false if you're doing a bulk operation</param>
|
||||
public void DestroyFixture(PhysicsComponent body, Fixture fixture, bool updates = true, FixturesComponent? manager = null)
|
||||
{
|
||||
if (!Resolve(body.OwnerUid, ref manager))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Assert world locked
|
||||
DebugTools.Assert(fixture.Body == body);
|
||||
DebugTools.Assert(manager.FixtureCount > 0);
|
||||
|
||||
if (!manager.Fixtures.Remove(fixture.ID))
|
||||
{
|
||||
Logger.ErrorS("fixtures", $"Tried to remove fixture from {body.Owner} that was already removed.");
|
||||
return;
|
||||
}
|
||||
|
||||
var edge = body.ContactEdges;
|
||||
|
||||
while (edge != null)
|
||||
{
|
||||
var contact = edge.Contact!;
|
||||
edge = edge.Next;
|
||||
|
||||
var fixtureA = contact.FixtureA;
|
||||
var fixtureB = contact.FixtureB;
|
||||
|
||||
if (fixture == fixtureA || fixture == fixtureB)
|
||||
{
|
||||
body.PhysicsMap?.ContactManager.Destroy(contact);
|
||||
}
|
||||
}
|
||||
|
||||
var broadphase = body.Broadphase;
|
||||
|
||||
if (broadphase != null)
|
||||
{
|
||||
_broadphaseSystem.DestroyProxies(broadphase, fixture);
|
||||
}
|
||||
|
||||
if (updates)
|
||||
{
|
||||
FixtureUpdate(manager, body);
|
||||
body.ResetMassData();
|
||||
manager.Dirty();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private void OnPhysicsShutdown(EntityUid uid, PhysicsComponent component, ComponentShutdown args)
|
||||
{
|
||||
if (EntityManager.GetComponent<MetaDataComponent>(uid).EntityLifeStage > EntityLifeStage.MapInitialized) return;
|
||||
EntityManager.RemoveComponent<FixturesComponent>(uid);
|
||||
}
|
||||
|
||||
private void OnPhysicsInit(ref PhysicsInitializedEvent ev)
|
||||
{
|
||||
EntityManager.EnsureComponent<FixturesComponent>(ev.Uid);
|
||||
}
|
||||
|
||||
private void OnGetState(EntityUid uid, FixturesComponent component, ref ComponentGetState args)
|
||||
{
|
||||
args.State = new FixtureManagerComponentState
|
||||
{
|
||||
Fixtures = component.Fixtures.Values.ToList(),
|
||||
};
|
||||
}
|
||||
|
||||
private void OnHandleState(EntityUid uid, FixturesComponent component, ref ComponentHandleState args)
|
||||
{
|
||||
if (args.Current is not FixtureManagerComponentState state) return;
|
||||
|
||||
if (!EntityManager.TryGetComponent(uid, out PhysicsComponent? physics))
|
||||
{
|
||||
DebugTools.Assert(false);
|
||||
Logger.ErrorS("physics", $"Tried to apply fixture state for {uid} which has name {nameof(PhysicsComponent)}");
|
||||
return;
|
||||
}
|
||||
|
||||
var toAddFixtures = new List<Fixture>();
|
||||
var toRemoveFixtures = new List<Fixture>();
|
||||
var computeProperties = false;
|
||||
|
||||
// Given a bunch of data isn't serialized need to sort of re-initialise it
|
||||
var newFixtures = new List<Fixture>(state.Fixtures.Count);
|
||||
foreach (var fixture in state.Fixtures)
|
||||
{
|
||||
var newFixture = new Fixture();
|
||||
fixture.CopyTo(newFixture);
|
||||
newFixture.Body = physics;
|
||||
newFixtures.Add(newFixture);
|
||||
}
|
||||
|
||||
// Add / update new fixtures
|
||||
foreach (var fixture in newFixtures)
|
||||
{
|
||||
var found = false;
|
||||
|
||||
foreach (var (_, existing) in component.Fixtures)
|
||||
{
|
||||
if (!fixture.ID.Equals(existing.ID)) continue;
|
||||
|
||||
if (!fixture.Equals(existing))
|
||||
{
|
||||
toAddFixtures.Add(fixture);
|
||||
toRemoveFixtures.Add(existing);
|
||||
}
|
||||
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
toAddFixtures.Add(fixture);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove old fixtures
|
||||
foreach (var (_, existing) in component.Fixtures)
|
||||
{
|
||||
var found = false;
|
||||
|
||||
foreach (var fixture in newFixtures)
|
||||
{
|
||||
if (fixture.ID.Equals(existing.ID))
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
toRemoveFixtures.Add(existing);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var fixture in toRemoveFixtures)
|
||||
{
|
||||
computeProperties = true;
|
||||
DestroyFixture(physics, fixture);
|
||||
}
|
||||
|
||||
// TODO: We also still need event listeners for shapes (Probably need C# events)
|
||||
// Or we could just make it so shapes can only be updated via fixturesystem which handles it
|
||||
// automagically (friends or something?)
|
||||
foreach (var fixture in toAddFixtures)
|
||||
{
|
||||
computeProperties = true;
|
||||
CreateFixture(physics, fixture);
|
||||
}
|
||||
|
||||
if (computeProperties)
|
||||
{
|
||||
physics.ResetMassData();
|
||||
}
|
||||
}
|
||||
|
||||
private string GetFixtureName(FixturesComponent component, Fixture fixture)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(fixture.ID)) return fixture.ID;
|
||||
|
||||
var i = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
++i;
|
||||
var name = $"fixture_{i}";
|
||||
var found = component.Fixtures.ContainsKey(name);
|
||||
|
||||
if (!found)
|
||||
{
|
||||
return name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates all of the cached physics information on the body derived from fixtures.
|
||||
/// </summary>
|
||||
public void FixtureUpdate(FixturesComponent component, PhysicsComponent? body = null)
|
||||
{
|
||||
if (!Resolve(component.OwnerUid, ref body))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var mask = 0;
|
||||
var layer = 0;
|
||||
var hard = false;
|
||||
|
||||
foreach (var (_, fixture) in component.Fixtures)
|
||||
{
|
||||
mask |= fixture.CollisionMask;
|
||||
layer |= fixture.CollisionLayer;
|
||||
hard |= fixture.Hard;
|
||||
}
|
||||
|
||||
body.ResetMassData();
|
||||
|
||||
// Normally this method is called when fixtures need to be dirtied anyway so no point in returning early I think
|
||||
body.CollisionMask = mask;
|
||||
body.CollisionLayer = layer;
|
||||
body.Hard = hard;
|
||||
component.Dirty();
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
private sealed class FixtureManagerComponentState : ComponentState
|
||||
{
|
||||
public List<Fixture> Fixtures = default!;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Robust.Shared.Analyzers;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Physics.Dynamics;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Utility;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Robust.Shared.Physics
|
||||
{
|
||||
/// <summary>
|
||||
/// Storage for physics fixtures
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// In its own component to decrease physics comp state size significantly.
|
||||
/// </remarks>
|
||||
[RegisterComponent]
|
||||
[NetworkedComponent]
|
||||
[Friend(typeof(FixtureSystem))]
|
||||
[ComponentProtoName("Fixtures")]
|
||||
public sealed class FixturesComponent : Component, ISerializationHooks
|
||||
{
|
||||
// This is a snowflake component whose main job is making physics states smaller for massive bodies
|
||||
// (e.g. grids)
|
||||
// Content generally shouldn't care about its existence.
|
||||
|
||||
public override string Name => "Fixtures";
|
||||
|
||||
[ViewVariables]
|
||||
public int FixtureCount => Fixtures.Count;
|
||||
|
||||
[ViewVariables]
|
||||
public readonly Dictionary<string, Fixture> Fixtures = new();
|
||||
|
||||
[DataField("fixtures")]
|
||||
[NeverPushInheritance]
|
||||
internal List<Fixture> SerializedFixtures = new();
|
||||
|
||||
void ISerializationHooks.BeforeSerialization()
|
||||
{
|
||||
// Can't assert the count is 0 because it's possible it gets re-serialized before init!
|
||||
if (SerializedFixtures.Count > 0) return;
|
||||
|
||||
foreach (var (_, fixture) in Fixtures)
|
||||
{
|
||||
SerializedFixtures.Add(fixture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -54,6 +54,8 @@ namespace Robust.Shared.Physics
|
||||
/// </summary>
|
||||
void DestroyContacts();
|
||||
|
||||
IReadOnlyList<Fixture> Fixtures { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The type of the body, which determines how collisions effect this object.
|
||||
/// </summary>
|
||||
@@ -81,7 +83,7 @@ namespace Robust.Shared.Physics
|
||||
/// <remarks>
|
||||
/// This is useful for triggers or such to detect collision without actually causing a blockage.
|
||||
/// </remarks>
|
||||
bool Hard { get; }
|
||||
bool Hard { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Inverse mass of the entity in kilograms (1 / Mass).
|
||||
|
||||
@@ -6,11 +6,19 @@ using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Shared.Physics
|
||||
{
|
||||
public partial class FixtureSystem
|
||||
public interface IShapeManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests whether a particular point is contained in the shape.
|
||||
/// Returns whether a particular point intersects the specified shape.
|
||||
/// </summary>
|
||||
bool TestPoint(IPhysShape shape, Transform xform, Vector2 worldPoint);
|
||||
|
||||
void GetMassData(IPhysShape shape, ref MassData data);
|
||||
}
|
||||
|
||||
public class ShapeManager : IShapeManager
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public bool TestPoint(IPhysShape shape, Transform xform, Vector2 worldPoint)
|
||||
{
|
||||
switch (shape)
|
||||
@@ -183,7 +183,7 @@ namespace Robust.Shared.Physics
|
||||
}
|
||||
}
|
||||
|
||||
internal void UpdateBroadphaseCache(BroadphaseComponent broadphase)
|
||||
private void UpdateBroadphaseCache(BroadphaseComponent broadphase)
|
||||
{
|
||||
var uid = broadphase.OwnerUid;
|
||||
|
||||
@@ -409,15 +409,14 @@ namespace Robust.Shared.Physics
|
||||
/// <summary>
|
||||
/// Remove all of our fixtures from the broadphase.
|
||||
/// </summary>
|
||||
private void DestroyProxies(PhysicsComponent body, FixturesComponent? manager = null)
|
||||
/// <param name="body"></param>
|
||||
private void DestroyProxies(PhysicsComponent body)
|
||||
{
|
||||
if (!Resolve(body.OwnerUid, ref manager)) return;
|
||||
|
||||
var broadphase = body.Broadphase;
|
||||
|
||||
if (broadphase == null) return;
|
||||
|
||||
foreach (var (_, fixture) in manager.Fixtures)
|
||||
foreach (var fixture in body._fixtures)
|
||||
{
|
||||
DestroyProxies(broadphase, fixture);
|
||||
}
|
||||
@@ -441,15 +440,9 @@ namespace Robust.Shared.Physics
|
||||
CreateProxies(body, true);
|
||||
}
|
||||
|
||||
internal void RemoveBody(PhysicsComponent body, FixturesComponent? manager = null)
|
||||
internal void RemoveBody(PhysicsComponent body)
|
||||
{
|
||||
// TODO: Would reaaalllyy like for this to not be false in future
|
||||
if (!Resolve(body.OwnerUid, ref manager, false))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DestroyProxies(body, manager);
|
||||
DestroyProxies(body);
|
||||
}
|
||||
|
||||
private void OnGridMove(EntityUid uid, MapGridComponent component, ref MoveEvent args)
|
||||
@@ -565,6 +558,91 @@ namespace Robust.Shared.Physics
|
||||
_queuedRotates.Enqueue(args);
|
||||
}
|
||||
|
||||
public void CreateFixture(PhysicsComponent body, Fixture fixture)
|
||||
{
|
||||
fixture.ID = body.GetFixtureName(fixture);
|
||||
body._fixtures.Add(fixture);
|
||||
body.FixtureCount += 1;
|
||||
fixture.Body = body;
|
||||
|
||||
// TODO: Assert world locked
|
||||
// Broadphase should be set in the future TM
|
||||
// Should only happen for nullspace / initializing entities
|
||||
if (body.Broadphase != null)
|
||||
{
|
||||
UpdateBroadphaseCache(body.Broadphase);
|
||||
CreateProxies(fixture, body.Owner.Transform.WorldPosition, false);
|
||||
}
|
||||
|
||||
// Supposed to be wrapped in density but eh
|
||||
body.ResetMassData();
|
||||
body.Dirty();
|
||||
// TODO: Set newcontacts to true.
|
||||
}
|
||||
|
||||
public Fixture CreateFixture(PhysicsComponent body, IPhysShape shape)
|
||||
{
|
||||
var fixture = new Fixture(body, shape);
|
||||
CreateFixture(body, fixture);
|
||||
return fixture;
|
||||
}
|
||||
|
||||
public void CreateFixture(PhysicsComponent body, IPhysShape shape, float mass)
|
||||
{
|
||||
// TODO: Make it take in density instead
|
||||
var fixture = new Fixture(body, shape) {Mass = mass};
|
||||
CreateFixture(body, fixture);
|
||||
}
|
||||
|
||||
public void DestroyFixture(PhysicsComponent body, string id)
|
||||
{
|
||||
var fixture = body.GetFixture(id);
|
||||
if (fixture == null) return;
|
||||
DestroyFixture(body, fixture);
|
||||
}
|
||||
|
||||
public void DestroyFixture(Fixture fixture)
|
||||
{
|
||||
DestroyFixture(fixture.Body, fixture);
|
||||
}
|
||||
|
||||
public void DestroyFixture(PhysicsComponent body, Fixture fixture)
|
||||
{
|
||||
// TODO: Assert world locked
|
||||
DebugTools.Assert(fixture.Body == body);
|
||||
DebugTools.Assert(body.FixtureCount > 0);
|
||||
|
||||
if (!body._fixtures.Remove(fixture))
|
||||
return;
|
||||
|
||||
var edge = body.ContactEdges;
|
||||
|
||||
while (edge != null)
|
||||
{
|
||||
var contact = edge.Contact!;
|
||||
edge = edge.Next;
|
||||
|
||||
var fixtureA = contact.FixtureA;
|
||||
var fixtureB = contact.FixtureB;
|
||||
|
||||
if (fixture == fixtureA || fixture == fixtureB)
|
||||
{
|
||||
body.PhysicsMap?.ContactManager.Destroy(contact);
|
||||
}
|
||||
}
|
||||
|
||||
var broadphase = GetBroadphase(fixture.Body);
|
||||
|
||||
if (broadphase != null)
|
||||
{
|
||||
DestroyProxies(broadphase, fixture);
|
||||
}
|
||||
|
||||
body.FixtureCount -= 1;
|
||||
body.ResetMassData();
|
||||
body.Dirty();
|
||||
}
|
||||
|
||||
private void SynchronizeFixtures(PhysicsComponent body, Vector2 worldPos, float worldRot)
|
||||
{
|
||||
// Logger.DebugS("physics", $"Synchronizing fixtures for {body.Owner}");
|
||||
@@ -655,7 +733,6 @@ namespace Robust.Shared.Physics
|
||||
if (body.Owner.Transform.MapID == MapId.Nullspace) return;
|
||||
|
||||
var worldPos = body.Owner.Transform.WorldPosition;
|
||||
var worldRot = body.Owner.Transform.WorldRotation;
|
||||
|
||||
// Outside of PVS (TODO Remove when PVS is better)
|
||||
if (float.IsNaN(worldPos.X) || float.IsNaN(worldPos.Y))
|
||||
@@ -679,7 +756,7 @@ namespace Robust.Shared.Physics
|
||||
|
||||
foreach (var fixture in body.Fixtures)
|
||||
{
|
||||
CreateProxies(fixture, worldPos, worldRot, useCache);
|
||||
CreateProxies(fixture, worldPos, useCache);
|
||||
}
|
||||
|
||||
// Ensure cache remains up to date if the broadphase is moving.
|
||||
@@ -696,7 +773,7 @@ namespace Robust.Shared.Physics
|
||||
/// <summary>
|
||||
/// Create the proxies for this fixture on the body's broadphase.
|
||||
/// </summary>
|
||||
internal void CreateProxies(Fixture fixture, Vector2 worldPos, Angle worldRot, bool useCache)
|
||||
private void CreateProxies(Fixture fixture, Vector2 worldPos, bool useCache)
|
||||
{
|
||||
// Ideally we would always just defer this until Update / FrameUpdate but that will have to wait for a future
|
||||
// PR for my own sanity.
|
||||
@@ -723,7 +800,7 @@ namespace Robust.Shared.Physics
|
||||
|
||||
Matrix3 broadphaseInvMatrix;
|
||||
(Vector2 Position, float Rotation) broadphaseTransform;
|
||||
var xform = EntityManager.GetComponent<TransformComponent>(broadphase.OwnerUid);
|
||||
var xform = broadphase.Owner.Transform;
|
||||
|
||||
if (useCache)
|
||||
{
|
||||
@@ -740,6 +817,7 @@ namespace Robust.Shared.Physics
|
||||
broadphaseTransform = (wp, (float) wr.Theta);
|
||||
}
|
||||
|
||||
var worldRot = fixture.Body.Owner.Transform.WorldRotation;
|
||||
var localPos = broadphaseInvMatrix.Transform(worldPos);
|
||||
|
||||
var transform = new Transform(localPos, worldRot - broadphaseTransform.Rotation);
|
||||
@@ -763,7 +841,7 @@ namespace Robust.Shared.Physics
|
||||
/// <summary>
|
||||
/// Destroy the proxies for this fixture on the broadphase.
|
||||
/// </summary>
|
||||
internal void DestroyProxies(BroadphaseComponent broadphase, Fixture fixture)
|
||||
private void DestroyProxies(BroadphaseComponent broadphase, Fixture fixture)
|
||||
{
|
||||
if (broadphase == null)
|
||||
{
|
||||
@@ -800,22 +878,12 @@ namespace Robust.Shared.Physics
|
||||
physicsComponent.Awake = true;
|
||||
}
|
||||
|
||||
public override void Shutdown()
|
||||
{
|
||||
base.Shutdown();
|
||||
var configManager = IoCManager.Resolve<IConfigurationManager>();
|
||||
configManager.UnsubValueChanged(CVars.BroadphaseExpand, SetBroadphaseExpand);
|
||||
_mapManager.MapCreated -= OnMapCreated;
|
||||
_mapManager.MapDestroyed -= OnMapDestroyed;
|
||||
}
|
||||
|
||||
#region Broadphase management
|
||||
|
||||
private void OnMapCreated(object? sender, MapEventArgs e)
|
||||
{
|
||||
if (e.Map == MapId.Nullspace) return;
|
||||
|
||||
EntityManager.EnsureComponent<BroadphaseComponent>(_mapManager.GetMapEntityId(e.Map));
|
||||
var mapEnt = _mapManager.GetMapEntity(e.Map);
|
||||
mapEnt.EnsureComponent<BroadphaseComponent>();
|
||||
_moveBuffer[e.Map] = new Dictionary<FixtureProxy, Box2>(64);
|
||||
}
|
||||
|
||||
@@ -825,9 +893,19 @@ namespace Robust.Shared.Physics
|
||||
_movedGrids.Remove(e.Map);
|
||||
}
|
||||
|
||||
public override void Shutdown()
|
||||
{
|
||||
base.Shutdown();
|
||||
var configManager = IoCManager.Resolve<IConfigurationManager>();
|
||||
configManager.UnsubValueChanged(CVars.BroadphaseExpand, SetBroadphaseExpand);
|
||||
_mapManager.MapCreated -= OnMapCreated;
|
||||
_mapManager.MapDestroyed -= OnMapDestroyed;
|
||||
}
|
||||
|
||||
private void HandleGridInit(GridInitializeEvent ev)
|
||||
{
|
||||
EntityManager.EnsureComponent<BroadphaseComponent>(ev.EntityUid);
|
||||
var grid = EntityManager.GetEntity(ev.EntityUid);
|
||||
grid.EnsureComponent<BroadphaseComponent>();
|
||||
}
|
||||
|
||||
private void HandleBroadphaseInit(EntityUid uid, BroadphaseComponent component, ComponentInit args)
|
||||
@@ -836,8 +914,6 @@ namespace Robust.Shared.Physics
|
||||
component.Tree = new DynamicTreeBroadPhase(capacity);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
internal BroadphaseComponent? GetBroadphase(PhysicsComponent body)
|
||||
{
|
||||
return GetBroadphase(body.Owner);
|
||||
@@ -908,6 +984,11 @@ namespace Robust.Shared.Physics
|
||||
}
|
||||
}
|
||||
|
||||
internal IEnumerable<BroadphaseComponent> GetBroadphases(MapId mapId, Vector2 worldPos)
|
||||
{
|
||||
return GetBroadphases(mapId, new Box2(worldPos, worldPos));
|
||||
}
|
||||
|
||||
private sealed class InvalidBroadphaseException : Exception
|
||||
{
|
||||
public InvalidBroadphaseException() {}
|
||||
|
||||
@@ -48,6 +48,7 @@ namespace Robust.Shared
|
||||
IoCManager.Register<IManifoldManager, CollisionManager>();
|
||||
IoCManager.Register<IIslandManager, IslandManager>();
|
||||
IoCManager.Register<IVerticesSimplifier, RamerDouglasPeuckerSimplifier>();
|
||||
IoCManager.Register<IShapeManager, ShapeManager>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,16 +113,6 @@ namespace Robust.UnitTesting
|
||||
compFactory.RegisterClass<PhysicsMapComponent>();
|
||||
}
|
||||
|
||||
if (!compFactory.AllRegisteredTypes.Contains(typeof(BroadphaseComponent)))
|
||||
{
|
||||
compFactory.RegisterClass<BroadphaseComponent>();
|
||||
}
|
||||
|
||||
if (!compFactory.AllRegisteredTypes.Contains(typeof(FixturesComponent)))
|
||||
{
|
||||
compFactory.RegisterClass<FixturesComponent>();
|
||||
}
|
||||
|
||||
if(entMan.EventBus == null)
|
||||
{
|
||||
entMan.Startup();
|
||||
|
||||
@@ -66,12 +66,9 @@ entities:
|
||||
var broady = new BroadPhaseSystem();
|
||||
var physics = new PhysicsSystem();
|
||||
var gridFixtures = new GridFixtureSystem();
|
||||
var fixtures = new FixtureSystem();
|
||||
// MOCKS WHY
|
||||
mock.Setup(m => m.GetEntitySystem<SharedBroadphaseSystem>()).Returns(broady);
|
||||
mock.Setup(m => m.GetEntitySystem<SharedPhysicsSystem>()).Returns(physics);
|
||||
mock.Setup(m => m.GetEntitySystem<GridFixtureSystem>()).Returns(gridFixtures);
|
||||
mock.Setup(m => m.GetEntitySystem<FixtureSystem>()).Returns(fixtures);
|
||||
|
||||
IoCManager.RegisterInstance<IEntitySystemManager>(mock.Object, true);
|
||||
//IoCManager.RegisterInstance<ICustomFormatManager>(mockFormat.Object, true);
|
||||
@@ -106,11 +103,7 @@ entities:
|
||||
var entMan = IoCManager.Resolve<IEntityManager>();
|
||||
|
||||
var mapId = map.CreateMap();
|
||||
// Yay test bullshit
|
||||
var mapUid = map.GetMapEntityId(mapId);
|
||||
entMan.EnsureComponent<PhysicsMapComponent>(mapUid);
|
||||
entMan.EnsureComponent<BroadphaseComponent>(mapUid);
|
||||
|
||||
map.GetMapEntity(mapId).EnsureComponent<PhysicsMapComponent>();
|
||||
var mapLoad = IoCManager.Resolve<IMapLoader>();
|
||||
var grid = mapLoad.LoadBlueprint(mapId, "/TestMap.yml");
|
||||
|
||||
|
||||
@@ -235,7 +235,6 @@ namespace Robust.UnitTesting.Server
|
||||
compFactory.RegisterClass<BroadphaseComponent>();
|
||||
compFactory.RegisterClass<ContainerManagerComponent>();
|
||||
compFactory.RegisterClass<PhysicsMapComponent>();
|
||||
compFactory.RegisterClass<FixturesComponent>();
|
||||
|
||||
_regDelegate?.Invoke(compFactory);
|
||||
|
||||
@@ -251,7 +250,6 @@ namespace Robust.UnitTesting.Server
|
||||
entitySystemMan.LoadExtraSystemType<MapSystem>();
|
||||
entitySystemMan.LoadExtraSystemType<DebugPhysicsSystem>();
|
||||
entitySystemMan.LoadExtraSystemType<BroadPhaseSystem>();
|
||||
entitySystemMan.LoadExtraSystemType<FixtureSystem>();
|
||||
entitySystemMan.LoadExtraSystemType<GridFixtureSystem>();
|
||||
entitySystemMan.LoadExtraSystemType<TransformSystem>();
|
||||
|
||||
|
||||
@@ -35,6 +35,10 @@ namespace Robust.UnitTesting.Shared.GameObjects.Systems
|
||||
{
|
||||
f.LoadString(Prototypes);
|
||||
})
|
||||
.RegisterDependencies(f =>
|
||||
{
|
||||
f.Register<IShapeManager, ShapeManager>();
|
||||
})
|
||||
.InitializeInstance();
|
||||
|
||||
var mapManager = sim.Resolve<IMapManager>();
|
||||
|
||||
@@ -17,7 +17,6 @@ namespace Robust.UnitTesting.Shared.Physics
|
||||
- type: Transform
|
||||
- type: Physics
|
||||
bodyType: Dynamic
|
||||
- type: Fixtures
|
||||
- type: CollisionWake
|
||||
";
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ namespace Robust.UnitTesting.Shared.Physics
|
||||
components:
|
||||
- type: Physics
|
||||
bodyType: Dynamic
|
||||
- type: Fixtures
|
||||
";
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -30,8 +30,8 @@ namespace Robust.UnitTesting.Shared.Physics
|
||||
{
|
||||
await _server.WaitIdleAsync();
|
||||
var entManager = _server.ResolveDependency<IEntityManager>();
|
||||
var fixtureSystem = _server.ResolveDependency<IEntitySystemManager>()
|
||||
.GetEntitySystem<FixtureSystem>();
|
||||
var broadphaseSystem = _server.ResolveDependency<IEntitySystemManager>()
|
||||
.GetEntitySystem<SharedBroadphaseSystem>();
|
||||
|
||||
await _server.WaitAssertion(() =>
|
||||
{
|
||||
@@ -39,7 +39,7 @@ namespace Robust.UnitTesting.Shared.Physics
|
||||
var box = boxEnt.AddComponent<PhysicsComponent>();
|
||||
var poly = new PolygonShape();
|
||||
poly.SetAsBox(0.5f, 0.5f);
|
||||
var fixture = fixtureSystem.CreateFixture(box, poly);
|
||||
var fixture = broadphaseSystem.CreateFixture(box, poly);
|
||||
fixture.Mass = 1f;
|
||||
box.FixedRotation = false;
|
||||
box.BodyType = BodyType.Dynamic;
|
||||
|
||||
@@ -7,21 +7,21 @@ using Robust.Shared.Physics.Collision.Shapes;
|
||||
namespace Robust.UnitTesting.Shared.Physics
|
||||
{
|
||||
[TestFixture]
|
||||
[TestOf(typeof(FixtureSystem))]
|
||||
public class FixtureShape_Test : RobustUnitTest
|
||||
[TestOf(typeof(IShapeManager))]
|
||||
public class ShapeManager_Test : RobustUnitTest
|
||||
{
|
||||
private FixtureSystem _shapeManager = default!;
|
||||
private IShapeManager _shapeManager = default!;
|
||||
|
||||
[OneTimeSetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_shapeManager = new FixtureSystem();
|
||||
_shapeManager = new ShapeManager();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestCirclePoint()
|
||||
{
|
||||
var circle = new PhysShapeCircle {Radius = 0.5f};
|
||||
var circle = new PhysShapeCircle() {Radius = 0.5f};
|
||||
var transform = new Transform(0f);
|
||||
var posA = Vector2.One;
|
||||
var posB = Vector2.Zero;
|
||||
@@ -49,11 +49,11 @@ namespace Robust.UnitTesting.Shared.Physics
|
||||
var entityManager = server.ResolveDependency<IEntityManager>();
|
||||
var mapManager = server.ResolveDependency<IMapManager>();
|
||||
var entitySystemManager = server.ResolveDependency<IEntitySystemManager>();
|
||||
var fixtureSystem = entitySystemManager.GetEntitySystem<FixtureSystem>();
|
||||
var broadphaseSystem = entitySystemManager.GetEntitySystem<SharedBroadphaseSystem>();
|
||||
MapId mapId;
|
||||
|
||||
const int columnCount = 1;
|
||||
const int rowCount = 15;
|
||||
var columnCount = 1;
|
||||
var rowCount = 15;
|
||||
PhysicsComponent[] bodies = new PhysicsComponent[columnCount * rowCount];
|
||||
Vector2 firstPos = Vector2.Zero;
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace Robust.UnitTesting.Shared.Physics
|
||||
Hard = true
|
||||
};
|
||||
|
||||
fixtureSystem.CreateFixture(ground, horizontalFixture);
|
||||
broadphaseSystem.CreateFixture(ground, horizontalFixture);
|
||||
|
||||
var vertical = new EdgeShape(new Vector2(10, 0), new Vector2(10, 10));
|
||||
var verticalFixture = new Fixture(ground, vertical)
|
||||
@@ -83,7 +83,7 @@ namespace Robust.UnitTesting.Shared.Physics
|
||||
Hard = true
|
||||
};
|
||||
|
||||
fixtureSystem.CreateFixture(ground, verticalFixture);
|
||||
broadphaseSystem.CreateFixture(ground, verticalFixture);
|
||||
|
||||
var xs = new[]
|
||||
{
|
||||
@@ -116,7 +116,7 @@ namespace Robust.UnitTesting.Shared.Physics
|
||||
Hard = true,
|
||||
};
|
||||
|
||||
fixtureSystem.CreateFixture(box, fixture);
|
||||
broadphaseSystem.CreateFixture(box, fixture);
|
||||
|
||||
bodies[j * rowCount + i] = box;
|
||||
}
|
||||
@@ -164,7 +164,8 @@ namespace Robust.UnitTesting.Shared.Physics
|
||||
var entityManager = server.ResolveDependency<IEntityManager>();
|
||||
var mapManager = server.ResolveDependency<IMapManager>();
|
||||
var entitySystemManager = server.ResolveDependency<IEntitySystemManager>();
|
||||
var fixtureSystem = entitySystemManager.GetEntitySystem<FixtureSystem>();
|
||||
var physicsSystem = entitySystemManager.GetEntitySystem<SharedPhysicsSystem>();
|
||||
var broadphaseSystem = entitySystemManager.GetEntitySystem<SharedBroadphaseSystem>();
|
||||
MapId mapId;
|
||||
|
||||
var columnCount = 1;
|
||||
@@ -187,7 +188,7 @@ namespace Robust.UnitTesting.Shared.Physics
|
||||
Hard = true
|
||||
};
|
||||
|
||||
fixtureSystem.CreateFixture(ground, horizontalFixture);
|
||||
broadphaseSystem.CreateFixture(ground, horizontalFixture);
|
||||
|
||||
var vertical = new EdgeShape(new Vector2(10, 0), new Vector2(10, 10));
|
||||
var verticalFixture = new Fixture(ground, vertical)
|
||||
@@ -197,7 +198,7 @@ namespace Robust.UnitTesting.Shared.Physics
|
||||
Hard = true
|
||||
};
|
||||
|
||||
fixtureSystem.CreateFixture(ground, verticalFixture);
|
||||
broadphaseSystem.CreateFixture(ground, verticalFixture);
|
||||
|
||||
var xs = new[]
|
||||
{
|
||||
@@ -226,7 +227,7 @@ namespace Robust.UnitTesting.Shared.Physics
|
||||
Hard = true,
|
||||
};
|
||||
|
||||
fixtureSystem.CreateFixture(circle, fixture);
|
||||
broadphaseSystem.CreateFixture(circle, fixture);
|
||||
|
||||
bodies[j * rowCount + i] = circle;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user