using System; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text.Json.Serialization; using Robust.Shared.Utility; namespace Robust.Shared.Maths { [Serializable] [StructLayout(LayoutKind.Sequential)] // ReSharper disable once InconsistentNaming public struct Vector2i : IEquatable, ISpanFormattable, IAdditionOperators, ISubtractionOperators, IMultiplyOperators, IMultiplyOperators, IComparisonOperators { public static readonly Vector2i Zero = (0, 0); public static readonly Vector2i One = (1, 1); public static readonly Vector2i Up = (0, 1); public static readonly Vector2i Down = (0, -1); public static readonly Vector2i Left = (-1, 0); public static readonly Vector2i Right = (1, 0); /// /// The X component of the Vector2i. /// [JsonInclude] public int X; /// /// The Y component of the Vector2i. /// [JsonInclude] public int Y; /// /// Construct a vector from its coordinates. /// /// X coordinate /// Y coordinate public Vector2i(int x, int y) { X = x; Y = y; } public static Vector2i ComponentMax(Vector2i a, Vector2i b) { return new(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y)); } public static Vector2i ComponentMin(Vector2i a, Vector2i b) { return new(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y)); } /// /// Gets the length (magnitude) of the vector. /// public readonly float Length { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => MathF.Sqrt(LengthSquared); } /// /// Gets the squared length of the vector. /// public readonly float LengthSquared { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => X * X + Y * Y; } /// /// Compare a vector to another vector and check if they are equal. /// /// Other vector to check. /// True if the two vectors are equal. public readonly bool Equals(Vector2i other) { return X == other.X && Y == other.Y; } /// /// Compare a vector to an object and check if they are equal. /// /// Other object to check. /// True if Object and vector are equal. public readonly override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) return false; return obj is Vector2i vector && Equals(vector); } /// /// Returns the hash code for this instance. /// /// A unique hash code for this instance. public readonly override int GetHashCode() { unchecked { return (X * 397) ^ Y; } } public static Vector2i operator -(Vector2i a, Vector2i b) { return new(a.X - b.X, a.Y - b.Y); } public static Vector2i operator -(Vector2i a, int b) { return new(a.X - b, a.Y - b); } public static Vector2i operator -(Vector2i a) { return new(-a.X, -a.Y); } public static Vector2i operator +(Vector2i a, Vector2i b) { return new(a.X + b.X, a.Y + b.Y); } public static Vector2i operator +(Vector2i a, int b) { return new(a.X + b, a.Y + b); } public static Vector2i operator *(Vector2i a, Vector2i b) { return new(a.X * b.X, a.Y * b.Y); } public static Vector2i operator *(Vector2i a, int scale) { return new(a.X * scale, a.Y * scale); } public static Vector2 operator *(Vector2i a, float scale) { return new(a.X * scale, a.Y * scale); } public static Vector2i operator /(Vector2i a, Vector2i b) { return new(a.X / b.X, a.Y / b.Y); } public static Vector2i operator /(Vector2i a, int scale) { return new(a.X / scale, a.Y / scale); } public static Vector2 operator /(Vector2i a, float scale) { return new(a.X / scale, a.Y / scale); } public static bool operator ==(Vector2i a, Vector2i b) { return a.Equals(b); } public static bool operator !=(Vector2i a, Vector2i b) { return !a.Equals(b); } public readonly void Deconstruct(out int x, out int y) { x = X; y = Y; } public static implicit operator Vector2(Vector2i vector) { return new(vector.X, vector.Y); } public static explicit operator Vector2i(Vector2 vector) { return new((int) vector.X, (int) vector.Y); } public static implicit operator Vector2i((int x, int y) tuple) { var (x, y) = tuple; return new Vector2i(x, y); } /// /// Returns a string that represents the current Vector2i. /// public override readonly string ToString() { return $"({X}, {Y})"; } public string ToString(string? format, IFormatProvider? formatProvider) { return ToString(); } public bool TryFormat( Span destination, out int charsWritten, ReadOnlySpan format, IFormatProvider? provider) { return FormatHelpers.TryFormatInto( destination, out charsWritten, $"({X}, {Y})"); } public static bool operator >(Vector2i left, Vector2i right) { return left.LengthSquared > right.LengthSquared; } public static bool operator >=(Vector2i left, Vector2i right) { return left.LengthSquared >= right.LengthSquared; } public static bool operator <(Vector2i left, Vector2i right) { return left.LengthSquared < right.LengthSquared; } public static bool operator <=(Vector2i left, Vector2i right) { return left.LengthSquared <= right.LengthSquared; } } }