namespace Zinnia.Tracking.Collision.Active.Operation { using System; using System.Collections.Generic; using UnityEngine; using Zinnia.Extension; /// /// Sorts the given collision collection based on which collision components are nearest to the specified . /// public class NearestSorter : MonoBehaviour { /// /// Compares two based on their containing 's distance to a given . /// protected class EventDataComparer : IComparer { [Tooltip("The position to check against.")] [SerializeField] private Vector3 sourcePosition; /// /// The position to check against. /// public Vector3 SourcePosition { get { return sourcePosition; } set { sourcePosition = value; } } /// public virtual int Compare(CollisionNotifier.EventData x, CollisionNotifier.EventData y) { Transform xTransform = x.ColliderData.GetContainingTransform(); Transform yTransform = y.ColliderData.GetContainingTransform(); if (xTransform == null && yTransform == null) { return 0; } float distance1 = xTransform != null ? Vector3.Distance(xTransform.position, SourcePosition) : float.MaxValue; float distance2 = yTransform != null ? Vector3.Distance(yTransform.position, SourcePosition) : float.MaxValue; return distance1.CompareTo(distance2); } } [Tooltip("The source to determine the closest collision to.")] [SerializeField] private GameObject source; /// /// The source to determine the closest collision to. /// public GameObject Source { get { return source; } set { source = value; } } /// /// The sorted list. /// public ActiveCollisionsContainer.EventData SortedList { get; protected set; } = new ActiveCollisionsContainer.EventData(); /// /// Emitted when the collection is sorted. /// public ActiveCollisionsContainer.ActiveCollisionUnityEvent Sorted = new ActiveCollisionsContainer.ActiveCollisionUnityEvent(); /// /// Compares two . /// protected static readonly EventDataComparer Comparer = new EventDataComparer(); /// /// The comparison does. /// protected static readonly Comparison Comparison = Comparer.Compare; /// /// Clears . /// public virtual void ClearSource() { if (!this.IsValidState()) { return; } Source = default; } /// /// Sorts the given collision collection by the collisions that are nearest to the source . /// /// The original collision collection. public virtual void DoSort(ActiveCollisionsContainer.EventData originalList) { Sort(originalList); } /// /// Sorts the given collision collection by the collisions that are nearest to the source . /// /// The original collision collection. /// The sorted collision collection. public virtual ActiveCollisionsContainer.EventData Sort(ActiveCollisionsContainer.EventData originalList) { if (!this.CheckIsActiveAndEnabled() || Source == null) { return originalList; } SortedList.Set(originalList); Comparer.SourcePosition = Source.transform.position; SortedList.ActiveCollisions.Sort(Comparison); Sorted?.Invoke(SortedList); return SortedList; } } }