#if MODULE_ENTITIES using Unity.Entities; namespace Pathfinding.ECS { using Unity.Transforms; public delegate void BeforeControlDelegate(Entity entity, float dt, ref LocalTransform localTransform, ref AgentCylinderShape shape, ref AgentMovementPlane movementPlane, ref DestinationPoint destination, ref MovementState movementState, ref MovementSettings movementSettings); public delegate void AfterControlDelegate(Entity entity, float dt, ref LocalTransform localTransform, ref AgentCylinderShape shape, ref AgentMovementPlane movementPlane, ref DestinationPoint destination, ref MovementState movementState, ref MovementSettings movementSettings, ref MovementControl movementControl); public delegate void BeforeMovementDelegate(Entity entity, float dt, ref LocalTransform localTransform, ref AgentCylinderShape shape, ref AgentMovementPlane movementPlane, ref DestinationPoint destination, ref MovementState movementState, ref MovementSettings movementSettings, ref MovementControl movementControl, ref ResolvedMovement resolvedMovement); /// /// Helper for adding and removing hooks to the FollowerEntity component. /// This is used to allow other systems to override the movement of the agent. /// /// See: /// public ref struct ManagedMovementOverrides { Entity entity; World world; public ManagedMovementOverrides (Entity entity, World world) { this.entity = entity; this.world = world; } public void AddBeforeControlCallback (BeforeControlDelegate value) { AddCallback(value); } public void RemoveBeforeControlCallback (BeforeControlDelegate value) { RemoveCallback(value); } public void AddAfterControlCallback (AfterControlDelegate value) { AddCallback(value); } public void RemoveAfterControlCallback (AfterControlDelegate value) { RemoveCallback(value); } public void AddBeforeMovementCallback (BeforeMovementDelegate value) { AddCallback(value); } public void RemoveBeforeMovementCallback (BeforeMovementDelegate value) { RemoveCallback(value); } void AddCallback(T callback) where T : System.Delegate where C : ManagedMovementOverride, IComponentData, new() { if (callback == null) throw new System.ArgumentNullException(nameof(callback)); if (world == null || !world.EntityManager.Exists(entity)) throw new System.InvalidOperationException("The entity does not exist. You can only set a callback when the FollowerEntity is active and has been enabled. If you are trying to set this during Awake or OnEnable, try setting it during Start instead."); if (!world.EntityManager.HasComponent(entity)) world.EntityManager.AddComponentData(entity, new C()); world.EntityManager.GetComponentData(entity).AddCallback(callback); } void RemoveCallback(T callback) where T : System.Delegate where C : ManagedMovementOverride, IComponentData, new() { if (callback == null) throw new System.ArgumentNullException(nameof(callback)); if (world == null || !world.EntityManager.Exists(entity)) return; if (!world.EntityManager.HasComponent(entity)) return; var comp = world.EntityManager.GetComponentData(entity); if (!comp.RemoveCallback(callback)) { world.EntityManager.RemoveComponent(entity); } } } /// /// Stores a delegate that can be used to override movement control and movement settings for a specific entity. /// This is used by the FollowerEntity to allow other systems to override the movement of the entity. /// /// See: /// public class ManagedMovementOverride : IComponentData where T : class, System.Delegate { public T callback; public void AddCallback(T callback) => this.callback = (T)System.Delegate.Combine(this.callback, callback); public bool RemoveCallback(T callback) => (this.callback = (T)System.Delegate.Remove(this.callback, callback)) != null; } // IJobEntity does not support generic jobs yet, so we have to make concrete component types for each delegate type public class ManagedMovementOverrideBeforeControl : ManagedMovementOverride, System.ICloneable { // No fields in this class can be cloned safely public object Clone() => new ManagedMovementOverrideBeforeControl(); } public class ManagedMovementOverrideAfterControl : ManagedMovementOverride { public object Clone() => new ManagedMovementOverrideAfterControl(); } public class ManagedMovementOverrideBeforeMovement : ManagedMovementOverride { public object Clone() => new ManagedMovementOverrideBeforeMovement(); } } #endif