// --------------------------------------------------------------------------------------------------------------------
//
// 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
}
}