Code/General/Vector3Extensions.cs
using ExtendedBox.General;
using ExtendedBox.Maths;
using Sandbox;
using System;
using System.Runtime.CompilerServices;
namespace ExtendedBox.General;
public static class Vector3Extensions
{
extension(Vector3)
{
/// <summary>
/// Calculates signed angle between two vectors based at look direction
/// <para>
/// Positive when rotation is counterclockwise<br />
/// Negative otherwise
/// </para>
/// </summary>
/// <param name="from"></param>
/// <param name="to"></param>
/// <param name="lookDirection"></param>
public static float GetSignedAngle(Vector3 from, Vector3 to, Vector3 lookDirection)
{
float angle = Vector3.GetAngle(from, to);
Vector3 cross = Vector3.Cross(from, to);
float sign = Vector3.Dot(lookDirection, cross);
return sign >= 0 ? angle : -angle;
}
}
public static Vector3 ProjectOnPlane(this Vector3 vector, Vector3 planeNormal) => Vector3.VectorPlaneProject(vector, planeNormal);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float DistanceSquared(this Vector3Int vector, Vector3 target) => target.DistanceSquared(vector);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float DistanceSquared(this Vector3Int vector, Vector3Int target) => ((Vector3)target).DistanceSquared(vector);
public static Vector3Int FloorToInt(this Vector3 vector) =>
new(vector.x.FloorToInt(), vector.y.FloorToInt(), vector.z.FloorToInt());
public static Vector3Int CeilToInt(this Vector3 vector) =>
new(vector.x.CeilToInt(), vector.y.CeilToInt(), vector.z.CeilToInt());
public static Vector3Int RoundToInt(this Vector3 vector) =>
new(vector.x.RoundToInt(), vector.y.RoundToInt(), vector.z.RoundToInt());
public static (Vector3 min, Vector3 max) ComponentMinMax(this Vector3 vector, Vector3 other) =>
(vector.ComponentMin(other), vector.ComponentMax(other));
public static (Vector3Int min, Vector3Int max) ComponentMinMax(this Vector3Int vector, Vector3Int other) =>
(vector.ComponentMin(other), vector.ComponentMax(other));
public static Vector3 SnapToGrid(this Vector3Int vector, float gridSize, bool sx = true, bool sy = true, bool sz = true) =>
((Vector3)vector).SnapToGrid(gridSize, sx, sy, sz);
public static bool AlmostEqual(this Vector3Int vector, Vector3 other, float delta = 0.0001f)
{
if(Math.Abs(vector.x - other.x) > delta)
return false;
if(Math.Abs(vector.y - other.y) > delta)
return false;
if(Math.Abs(vector.z - other.z) > delta)
return false;
return true;
}
public static string ToString(this Vector3 vector, string? format)
{
return $"{vector.x.ToString(format)},{vector.y.ToString(format)},{vector.z.ToString(format)}";
}
public static string ToString(this Vector3 vector, string? format, IFormatProvider? formatProvider)
{
return $"{vector.x.ToString(format, formatProvider)},{vector.y.ToString(format, formatProvider)},{vector.z.ToString(format, formatProvider)}";
}
public static string ToString(this Vector3 vector, IFormatProvider? formatProvider)
{
return $"{vector.x.ToString(formatProvider)},{vector.y.ToString(formatProvider)},{vector.z.ToString(formatProvider)}";
}
public static string ToString(this Vector3Int vector, string? format)
{
return $"{vector.x.ToString(format)},{vector.y.ToString(format)},{vector.z.ToString(format)}";
}
public static string ToString(this Vector3Int vector, string? format, IFormatProvider? formatProvider)
{
return $"{vector.x.ToString(format, formatProvider)},{vector.y.ToString(format, formatProvider)},{vector.z.ToString(format, formatProvider)}";
}
public static string ToString(this Vector3Int vector, IFormatProvider? formatProvider)
{
return $"{vector.x.ToString(formatProvider)},{vector.y.ToString(formatProvider)},{vector.z.ToString(formatProvider)}";
}
}