Skip to content

Commit

Permalink
Yet another rework on trigger physics
Browse files Browse the repository at this point in the history
  • Loading branch information
saint11 committed Dec 20, 2024
1 parent 70882b3 commit a3a2c80
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 25 deletions.
15 changes: 15 additions & 0 deletions src/Murder.Editor/Utilities/EntityInspector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ private static bool StartEntityTree(World world, Entity entity, string entityNam
{
cameraMan.RemoveIdTarget();
}
ImGuiHelpers.HelpTooltip("Recover camera");
}
else
{
Expand All @@ -146,9 +147,23 @@ private static bool StartEntityTree(World world, Entity entity, string entityNam
{
cameraMan.SetIdTarget(entity.EntityId);
}
ImGuiHelpers.HelpTooltip("Center camera on entity");

}
ImGui.PopStyleColor();
ImGui.SameLine();

if (entity.Parent == null)
{
ImGui.PushStyleColor(ImGuiCol.ButtonHovered, Game.Profile.Theme.Red);
if (ImGui.Button(""))
{
entity.Destroy();
}
ImGui.PopStyleColor();

ImGui.SameLine();
}
}

if (pushTree)
Expand Down
75 changes: 50 additions & 25 deletions src/Murder/Systems/Physics/TriggerPhysicsSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Bang.Systems;
using Murder.Components;
using Murder.Core.Physics;
using Murder.Helpers;
using Murder.Services;
using Murder.Utilities;
using System.Collections.Immutable;
Expand All @@ -21,44 +22,76 @@ public class TriggerPhysicsSystem : IReactiveSystem, IFixedUpdateSystem
// Used for reclycing over the same collision cache.
private readonly HashSet<int> _collisionVisitedEntities = new(516);

private readonly Dictionary<int, bool> _entitiesOnWatch = new(256);
private readonly Dictionary<int, (Entity, ImmutableHashSet<int>, bool)> _entitiesOnWatch = new(256);

private void WatchEntities(ImmutableArray<Entity> entities)
private void WatchEntities(ImmutableArray<Entity> entities, World world)
{
for (int i = 0; i < entities.Length; i++)
{
Entity entity = entities[i];
if (entity.TryGetCollider() is not ColliderComponent collider)
if (_entitiesOnWatch.ContainsKey(entity.EntityId))
{
// This entity no longer has a collider
continue;
}
_entitiesOnWatch[entity.EntityId] = (collider.Layer & (CollisionLayersBase.TRIGGER)) == 0;

bool isActor = false;
if (entity.TryGetCollider() is ColliderComponent collider)
{
isActor = (collider.Layer & (CollisionLayersBase.TRIGGER)) == 0;
}

if (entity.IsDestroyed)
{
// Destroyed entities are not added to the watch list.
// But we message them immediately.

if (entity.TryGetCollisionCache() is not CollisionCacheComponent destroyedCollisionCache)
{
continue;
}

foreach (var other in destroyedCollisionCache.GetCollidingEntities(world))
{
entity.SendOnCollisionMessage(other.EntityId, CollisionDirection.Exit);
other.SendOnCollisionMessage(entity.EntityId, CollisionDirection.Exit);
}

continue;
}

if (entity.TryGetCollisionCache() is CollisionCacheComponent collisionCache)
{
_entitiesOnWatch[entity.EntityId] = (entity, collisionCache.CollidingWith, isActor);
}
else
{
_entitiesOnWatch[entity.EntityId] = (entity, [], isActor);
}
}
}

public void OnDeactivated(World world, ImmutableArray<Entity> entities)
{
WatchEntities(entities);
WatchEntities(entities, world);
}

public void OnRemoved(World world, ImmutableArray<Entity> entities)
{
WatchEntities(entities);
WatchEntities(entities, world);
}
public void OnActivated(World world, ImmutableArray<Entity> entities)
{
WatchEntities(entities);
WatchEntities(entities, world);
}

public void OnAdded(World world, ImmutableArray<Entity> entities)
{
WatchEntities(entities);
WatchEntities(entities, world);
}

public void OnModified(World world, ImmutableArray<Entity> entities)
{
WatchEntities(entities);
WatchEntities(entities, world);
}

public void FixedUpdate(Context context)
Expand All @@ -68,31 +101,23 @@ public void FixedUpdate(Context context)
return;
}

ImmutableArray<Entity> collisionsCache = context.World.GetEntitiesWith(typeof(CollisionCacheComponent));
Quadtree qt = Quadtree.GetOrCreateUnique(context.World);

foreach ((int entityId, bool thisIsAnActor) in _entitiesOnWatch)
foreach ((int entityId, (Entity entity, ImmutableHashSet<int> collidingWith, bool thisIsAnActor)) in _entitiesOnWatch)
{
Entity? entity = context.World.TryGetEntity(entityId);

// Remove deactivated or destroyed entities from the collision cache and send exit messages.
if (entity is null || !entity.IsActive || entity.IsDestroyed)
if (!entity.IsActive || entity.IsDestroyed)
{
foreach (Entity otherCached in collisionsCache)
foreach (int otherCachedId in collidingWith)
{
if (PhysicsServices.RemoveFromCollisionCache(otherCached, entityId))
Entity? otherCached = context.World.TryGetEntity(otherCachedId);
if (otherCached != null && PhysicsServices.RemoveFromCollisionCache(otherCached, entityId))
{
// Should we really send the ID of the deleted entity?
if (entity != null)
{
otherCached.SendOnCollisionMessage(entityId, CollisionDirection.Exit);
}
// There's no need to send the message back, as the entity is already destroyed.
entity.SendOnCollisionMessage(otherCached.EntityId, CollisionDirection.Exit);
otherCached.SendOnCollisionMessage(entityId, CollisionDirection.Exit);
}
}

entity?.RemoveCollisionCache();
continue;
}

// Check for active entities.
Expand Down

0 comments on commit a3a2c80

Please sign in to comment.