// MIT License - Copyright (c) 2023 wallstop // Full license text: https://github.com/wallstop/unity-helpers/blob/main/LICENSE namespace WallstopStudios.UnityHelpers.Utils { using System; using System.Collections.Generic; using UnityEngine; using WallstopStudios.UnityHelpers.Core.Helper; /// /// Provides value and ordering comparisons for instances and /// offers helpers for duplicating them without mutating the original event. /// /// /// Unity does not expose an implementation for /// . This comparer inspects the fields Unity uses for dispatching /// events (time, function name, parameters, and message options) and treats two events as equal /// only when all of those values match. /// public sealed class AnimationEventEqualityComparer : EqualityComparer, IComparer { /// /// Gets a globally shared comparer instance to avoid unnecessary allocations. /// public static readonly AnimationEventEqualityComparer Instance = new(); private AnimationEventEqualityComparer() { } /// /// Creates a shallow copy of the supplied by cloning its /// equatable values. /// /// Event instance to duplicate, or null to skip copying. /// A new carrying the same values, or null. public AnimationEvent Copy(AnimationEvent instance) { if (instance == null) { return null; } AnimationEvent copy = new(); CopyInto(copy, instance); return copy; } /// /// Copies all equatable values from into /// without creating a new . /// /// Destination instance that receives the values. /// Source instance that provides the values. public void CopyInto(AnimationEvent into, AnimationEvent parameters) { if (into == null || parameters == null) { return; } into.time = parameters.time; into.functionName = parameters.functionName; into.intParameter = parameters.intParameter; into.floatParameter = parameters.floatParameter; into.stringParameter = parameters.stringParameter; into.objectReferenceParameter = parameters.objectReferenceParameter; into.messageOptions = parameters.messageOptions; } /// public override bool Equals(AnimationEvent lhs, AnimationEvent rhs) { if (ReferenceEquals(lhs, rhs)) { return true; } if (lhs == null || rhs == null) { return false; } // ReSharper disable once CompareOfFloatsByEqualityOperator if (lhs.time != rhs.time) { return false; } if (lhs.functionName != rhs.functionName) { return false; } if (lhs.intParameter != rhs.intParameter) { return false; } // ReSharper disable once CompareOfFloatsByEqualityOperator if (lhs.floatParameter != rhs.floatParameter) { return false; } if (lhs.stringParameter != rhs.stringParameter) { return false; } if (lhs.objectReferenceParameter != rhs.objectReferenceParameter) { return false; } if (lhs.messageOptions != rhs.messageOptions) { return false; } return true; } /// public override int GetHashCode(AnimationEvent instance) { return Objects.HashCode( instance.time, instance.functionName, instance.intParameter, instance.floatParameter, instance.stringParameter, instance.objectReferenceParameter, instance.messageOptions ); } /// /// Orders two instances using their firing time followed by the /// textual and numeric parameters. /// /// First event to compare. /// Second event to compare. /// /// An integer less than zero when should come before /// , zero when they are equivalent, or greater than zero otherwise. /// public int Compare(AnimationEvent lhs, AnimationEvent rhs) { if (ReferenceEquals(lhs, rhs)) { return 0; } if (ReferenceEquals(null, rhs)) { return 1; } if (ReferenceEquals(null, lhs)) { return -1; } int timeComparison = lhs.time.CompareTo(rhs.time); if (timeComparison != 0) { return timeComparison; } int functionNameComparison = string.Compare( lhs.functionName, rhs.functionName, StringComparison.Ordinal ); if (functionNameComparison != 0) { return functionNameComparison; } int intParameterComparison = lhs.intParameter.CompareTo(rhs.intParameter); if (intParameterComparison != 0) { return intParameterComparison; } int stringParameterComparison = string.Compare( lhs.stringParameter, rhs.stringParameter, StringComparison.Ordinal ); if (stringParameterComparison != 0) { return stringParameterComparison; } return lhs.floatParameter.CompareTo(rhs.floatParameter); } } }