// -------------------------------------------------------------------------------------------------------------------- // // Copyright (c) VRMADA, All rights reserved. // // -------------------------------------------------------------------------------------------------------------------- using UltimateXR.Core; using UnityEngine; namespace UltimateXR.Extensions.System.Math { /// /// extensions. /// public static class FloatExt { #region Public Methods /// /// Compares two float values for equality with a specified precision threshold. /// /// The first float to compare /// The second float to compare /// /// The precision threshold for float comparisons. Defaults to /// . /// /// /// true if the float are equal; otherwise, false. /// public static bool EqualsUsingPrecision(this float a, float b, float precisionThreshold = UxrConstants.Math.DefaultPrecisionThreshold) { return Mathf.Abs(a - b) <= precisionThreshold; } /// /// Converts a float value representing time in seconds to a formatted string value. /// /// Seconds to convert /// Whether to exclude the hours from the string if they are 0 /// Whether to include the milliseconds in the string /// /// Formatted time hh:mm::ss:mmm applying and /// constraints. /// public static string SecondsToTimeString(this float self, bool excludeHoursIfZero = false, bool includeMilliseconds = false) { int hours = Mathf.FloorToInt(self / 3600.0f); int minutes = Mathf.FloorToInt((self - hours * 3600.0f) / 60.0f); int seconds = Mathf.FloorToInt(self - hours * 3600.0f - minutes * 60.0f); int milliseconds = (int)(self * 1000 % 1000); if (hours >= 1) { return includeMilliseconds ? $"{hours:D2}:{minutes:D2}:{seconds:D2}:{milliseconds:D3}" : $"{hours:D2}:{minutes:D2}:{seconds:D2}"; } if (excludeHoursIfZero) { return includeMilliseconds ? $"{minutes:D2}:{seconds:D2}:{milliseconds:D3}" : $"{minutes:D2}:{seconds:D2}"; } return includeMilliseconds ? $"{hours:D2}:{minutes:D2}:{seconds:D2}:{milliseconds:D3}" : $"{hours:D2}:{minutes:D2}:{seconds:D2}"; } /// /// Checks if a float value is or is very close to zero. /// /// Value to check /// Boolean telling whether the float value is or is very close to zero public static bool IsAlmostZero(this float self) { return Mathf.Approximately(self, 0.0f); } /// /// Given a value in degrees, returns the same angle making sure it's in range [-180, 180]. For example, an /// input of -380.3 would return -20.3. /// /// Value to process /// Degrees in range between [-180, 180] public static float ToEuler180(this float self) { float angle = self % 360.0f; if (angle > 180.0f) { angle -= 360.0f; } else if (angle < -180.0f) { angle += 360.0f; } return angle; } /// /// Clamps a value so that it doesn't go beyond a given range. /// /// Value to clamp /// Minimum value /// Maximum value /// Clamped value between [min, max] public static float Clamp(this ref float self, float min, float max) { self = Mathf.Clamp(self, min, max); return self; } /// /// Returns a clamped value. /// /// Value to clamp /// Minimum value /// Maximum value /// Clamped value between [min, max] public static float Clamped(this float self, float min, float max) { return Mathf.Clamp(self, min, max); } /// /// Clamps a value to [0.0, 1.0]. /// /// Value to clamp /// Clamped value between [0.0, 1.0] public static float Clamp(this ref float self) { self = Mathf.Clamp01(self); return self; } /// /// Returns a clamped value in range [0.0, 1.0]. /// /// Value to clamp /// Clamped value between [0.0, 1.0] public static float Clamped(this float self) { return Mathf.Clamp01(self); } /// /// Returns the value from the set with the maximum absolute value, but keeping the sign. /// /// Set of values /// Value with the maximum absolute value keeping the sign public static float SignedAbsMax(params float[] values) { float signedAbsoluteMax = 0.0f; bool initialized = false; foreach (float value in values) { if (!initialized || Mathf.Abs(value) > Mathf.Abs(signedAbsoluteMax)) { initialized = true; signedAbsoluteMax = value; } } return signedAbsoluteMax; } #endregion } }