Skip to content

Commit

Permalink
Contact QOL stuff
Browse files Browse the repository at this point in the history
Only just made the enumerator version need to test with AI branch had an IEnumerable before.
metalgearsloth committed Aug 22, 2024
1 parent f03c006 commit f6e1ef7
Showing 4 changed files with 111 additions and 1 deletion.
23 changes: 23 additions & 0 deletions Robust.Shared/Physics/Dynamics/Contacts/Contact.cs
Original file line number Diff line number Diff line change
@@ -349,6 +349,29 @@ public override int GetHashCode()
// TODO: Need to suss this out
return HashCode.Combine(EntityA, EntityB);
}

/// <summary>
/// Gets the other ent for this contact.
/// </summary>
public EntityUid OtherEnt(EntityUid uid)
{
if (uid == EntityA)
return EntityB;
else if (uid == EntityB)
return EntityA;

throw new InvalidOperationException();
}

public (string Id, Fixture) OtherFixture(EntityUid uid)
{
if (uid == EntityA)
return (FixtureBId, FixtureB!);
else if (uid == EntityB)
return (FixtureAId, FixtureA!);

throw new InvalidOperationException();
}
}

[Flags]
1 change: 1 addition & 0 deletions Robust.Shared/Physics/Systems/FixtureSystem.cs
Original file line number Diff line number Diff line change
@@ -116,6 +116,7 @@ internal void CreateFixture(
// Don't need to ResetMassData as FixtureUpdate already does it.
Dirty(uid, manager);
}

// TODO: Set newcontacts to true.
}

2 changes: 1 addition & 1 deletion Robust.Shared/Physics/Systems/SharedBroadphaseSystem.cs
Original file line number Diff line number Diff line change
@@ -416,7 +416,7 @@ public void RegenerateContacts(EntityUid uid, PhysicsComponent body, FixturesCom
}
}

private void TouchProxies(EntityUid mapId, Matrix3x2 broadphaseMatrix, Fixture fixture)
internal void TouchProxies(EntityUid mapId, Matrix3x2 broadphaseMatrix, Fixture fixture)
{
foreach (var proxy in fixture.Proxies)
{
86 changes: 86 additions & 0 deletions Robust.Shared/Physics/Systems/SharedPhysicsSystem.Contacts.cs
Original file line number Diff line number Diff line change
@@ -30,7 +30,9 @@
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Numerics;
using JetBrains.Annotations;
using Microsoft.Extensions.ObjectPool;
using Robust.Shared.GameObjects;
using Robust.Shared.Maths;
@@ -741,6 +743,90 @@ protected bool ShouldCollide(

return true;
}

/// <summary>
/// Will destroy all contacts and queue for rebuild.
/// Useful if you have one that may no longer be relevant and don't want to destroy it directly.
/// </summary>
public void RegenerateContacts(Entity<PhysicsComponent?> entity)
{
if (!PhysicsQuery.Resolve(entity.Owner, ref entity.Comp))
return;

_broadphase.RegenerateContacts(entity.Owner, entity.Comp);
}

/// <summary>
/// Returns the number of touching contacts this entity has.
/// </summary>
/// <param name="ignoredFixtureId">Fixture we should ignore if applicable</param>
[Pure]
public int GetTouchingContacts(Entity<FixturesComponent?> entity, string? ignoredFixtureId = null)
{
if (!_fixturesQuery.Resolve(entity.Owner, ref entity.Comp))
return 0;

var count = 0;

foreach (var (id, fixture) in entity.Comp.Fixtures)
{
if (ignoredFixtureId == id)
continue;

foreach (var contact in fixture.Contacts.Values)
{
if (!contact.IsTouching)
continue;

count++;
}
}

return count;
}

/// <summary>
/// Returns all of this entity's contacts.
/// </summary>
[Pure]
public ContactEnumerator GetContacts(Entity<FixturesComponent?> entity)
{
if (!_fixturesQuery.Resolve(entity.Owner, ref entity.Comp))
return ContactEnumerator.Empty;

return new ContactEnumerator(entity.Comp);
}
}

public record struct ContactEnumerator
{
public static readonly ContactEnumerator Empty = new();

private Dictionary<string, Fixture>.ValueCollection.Enumerator _fixtureEnumerator;
private Dictionary<Fixture, Contact>.ValueCollection.Enumerator _contactEnumerator;

public ContactEnumerator(FixturesComponent fixtures)
{
_fixtureEnumerator = fixtures.Fixtures.Values.GetEnumerator();
_contactEnumerator = _fixtureEnumerator.Current.Contacts.Values.GetEnumerator();
}

public bool MoveNext(out Contact? contact)
{
if (!_contactEnumerator.MoveNext())
{
if (!_fixtureEnumerator.MoveNext())
{
contact = null;
return false;
}

_contactEnumerator = _fixtureEnumerator.Current.Contacts.Values.GetEnumerator();
}

contact = _contactEnumerator.Current;
return true;
}
}

internal enum ContactStatus : byte

0 comments on commit f6e1ef7

Please sign in to comment.