mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-01-02 11:28:19 -05:00
This commit imports the C# engine code and game files, excluding C++ source code. [Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
487 lines
13 KiB
C#
487 lines
13 KiB
C#
using Sandbox;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text.Json.Serialization;
|
|
|
|
[JsonConverter( typeof( Sandbox.Internal.JsonConvert.Vector2IntConverter ) )]
|
|
[StructLayout( LayoutKind.Sequential )]
|
|
public struct Vector2Int : IEquatable<Vector2Int>, IParsable<Vector2Int>
|
|
{
|
|
/// <summary>
|
|
/// The X component of this integer vector.
|
|
/// </summary>
|
|
[ActionGraphInclude( AutoExpand = true )]
|
|
[JsonInclude]
|
|
public int x;
|
|
|
|
/// <summary>
|
|
/// The Y component of this integer vector.
|
|
/// </summary>
|
|
[ActionGraphInclude( AutoExpand = true )]
|
|
[JsonInclude]
|
|
public int y;
|
|
|
|
/// <summary>
|
|
/// Initializes an integer vector with given components.
|
|
/// </summary>
|
|
/// <param name="x">The X component.</param>
|
|
/// <param name="y">The Y component.</param>
|
|
[ActionGraphNode( "vec2int.new" ), Title( "Vector2Int" ), Group( "Math/Geometry/Vector2Int" )]
|
|
public Vector2Int( int x, int y )
|
|
{
|
|
this.x = x;
|
|
this.y = y;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializes an integer vector with all components set to the same value.
|
|
/// </summary>
|
|
/// <param name="all">The value of the X and Y components.</param>
|
|
public Vector2Int( int all = 0 ) : this( all, all )
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializes an integer vector with given components from another integer vector.
|
|
/// </summary>
|
|
public Vector2Int( Vector2Int vector2Int )
|
|
{
|
|
x = vector2Int.x;
|
|
y = vector2Int.y;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializes an integer vector with given components from another integer vector, discarding the Z component.
|
|
/// </summary>
|
|
public Vector2Int( Vector3Int vector3Int )
|
|
{
|
|
x = vector3Int.x;
|
|
y = vector3Int.y;
|
|
}
|
|
|
|
/// <summary>
|
|
/// An integer vector with all components set to 1.
|
|
/// </summary>
|
|
public static readonly Vector2Int One = new( 1 );
|
|
|
|
/// <summary>
|
|
/// An integer vector with all components set to 0.
|
|
/// </summary>
|
|
public static readonly Vector2Int Zero = new( 0 );
|
|
|
|
/// <summary>
|
|
/// An integer vector with X set to 1. This represents the right direction.
|
|
/// </summary>
|
|
public static readonly Vector2Int Right = new( 1, 0 );
|
|
|
|
/// <summary>
|
|
/// An integer vector with X set to -1. This represents the left direction.
|
|
/// </summary>
|
|
public static readonly Vector2Int Left = new( -1, 0 );
|
|
|
|
/// <summary>
|
|
/// An integer vector with Y set to 1. This represents the up direction.
|
|
/// </summary>
|
|
public static readonly Vector2Int Up = new( 0, -1 );
|
|
|
|
/// <summary>
|
|
/// An integer vector with Y set to -1. This represents the down direction.
|
|
/// </summary>
|
|
public static readonly Vector2Int Down = new( 0, 1 );
|
|
|
|
/// <summary>
|
|
/// Formats the integer vector as a string "x,y".
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public override string ToString()
|
|
{
|
|
return $"{x},{y}";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns a unit version of this vector. Keep in mind this returns a Vector2 and not a Vector2Int.
|
|
/// </summary>
|
|
public readonly Vector2 Normal
|
|
{
|
|
get
|
|
{
|
|
if ( IsZeroLength ) return this;
|
|
|
|
return (Vector2)this / Length;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Return the angle of this vector in degrees, always between 0 and 360.
|
|
/// </summary>
|
|
public readonly float Degrees => System.MathF.Atan2( x, -y ).RadianToDegree().NormalizeDegrees();
|
|
|
|
|
|
// Vector2Int x Number Operators
|
|
public static Vector2Int operator +( Vector2Int c1, int c2 )
|
|
{
|
|
return new Vector2Int( c1.x + c2, c1.y + c2 );
|
|
}
|
|
|
|
public static Vector2 operator +( Vector2Int c1, float c2 )
|
|
{
|
|
return new Vector2( c1.x + c2, c1.y + c2 );
|
|
}
|
|
public static Vector2Int operator -( Vector2Int c1, int c2 )
|
|
{
|
|
return new Vector2Int( c1.x - c2, c1.y - c2 );
|
|
}
|
|
|
|
public static Vector2 operator -( Vector2Int c1, float c2 )
|
|
{
|
|
return new Vector2( c1.x - c2, c1.y - c2 );
|
|
}
|
|
public static Vector2Int operator *( Vector2Int c1, int c2 )
|
|
{
|
|
return new Vector2Int( c1.x * c2, c1.y * c2 );
|
|
}
|
|
|
|
public static Vector2 operator *( Vector2Int c1, float c2 )
|
|
{
|
|
return new Vector2( c1.x * c2, c1.y * c2 );
|
|
}
|
|
public static Vector2Int operator /( Vector2Int c1, int c2 )
|
|
{
|
|
return new Vector2Int( c1.x / c2, c1.y / c2 );
|
|
}
|
|
|
|
public static Vector2 operator /( Vector2Int c1, float c2 )
|
|
{
|
|
return new Vector2( c1.x / c2, c1.y / c2 );
|
|
}
|
|
|
|
|
|
// Vector2Int x Vector2Int Operators
|
|
public static Vector2Int operator +( Vector2Int c1, Vector2Int c2 )
|
|
{
|
|
return new Vector2Int( c1.x + c2.x, c1.y + c2.y );
|
|
}
|
|
public static Vector2Int operator -( Vector2Int c1, Vector2Int c2 )
|
|
{
|
|
return new Vector2Int( c1.x - c2.x, c1.y - c2.y );
|
|
}
|
|
public static Vector2Int operator /( Vector2Int c1, Vector2Int c2 )
|
|
{
|
|
return new Vector2Int( c1.x / c2.x, c1.y / c2.y );
|
|
}
|
|
public static Vector2Int operator *( Vector2Int c1, Vector2Int c2 )
|
|
{
|
|
return new Vector2Int( c1.x * c2.x, c1.y * c2.y );
|
|
}
|
|
|
|
// Vector2Int x Vector2 Operators
|
|
public static Vector2 operator +( Vector2Int c1, Vector2 c2 )
|
|
{
|
|
return new Vector2( c1.x + c2.x, c1.y + c2.y );
|
|
}
|
|
public static Vector2 operator +( Vector2 c1, Vector2Int c2 )
|
|
{
|
|
return new Vector2( c1.x + c2.x, c1.y + c2.y );
|
|
}
|
|
public static Vector2 operator -( Vector2 c1, Vector2Int c2 )
|
|
{
|
|
return new Vector2( c1.x - c2.x, c1.y - c2.y );
|
|
}
|
|
public static Vector2 operator -( Vector2Int c1, Vector2 c2 )
|
|
{
|
|
return new Vector2( c1.x - c2.x, c1.y - c2.y );
|
|
}
|
|
public static Vector2 operator *( Vector2 c1, Vector2Int c2 )
|
|
{
|
|
return new Vector2( c1.x * c2.x, c1.y * c2.y );
|
|
}
|
|
public static Vector2 operator *( Vector2Int c1, Vector2 c2 )
|
|
{
|
|
return new Vector2( c1.x * c2.x, c1.y * c2.y );
|
|
}
|
|
public static Vector2 operator /( Vector2Int c1, Vector2 c2 )
|
|
{
|
|
return new Vector2( c1.x / c2.x, c1.y / c2.y );
|
|
}
|
|
|
|
public static Vector2 operator /( Vector2 c1, Vector2Int c2 )
|
|
{
|
|
return new Vector2( c1.x / c2.x, c1.y / c2.y );
|
|
}
|
|
|
|
// Vector2Int x Vector3 Operators
|
|
public static Vector3 operator +( Vector3 c1, Vector2Int c2 )
|
|
{
|
|
return new Vector3( c1.x + c2.x, c1.y + c2.y, c1.z );
|
|
}
|
|
public static Vector3 operator +( Vector2Int c1, Vector3 c2 )
|
|
{
|
|
return new Vector3( c1.x + c2.x, c1.y + c2.y, c2.z );
|
|
}
|
|
public static Vector3 operator -( Vector2Int c1, Vector3 c2 )
|
|
{
|
|
return new Vector3( c1.x - c2.x, c1.y - c2.y, -c2.z );
|
|
}
|
|
public static Vector3 operator -( Vector3 c1, Vector2Int c2 )
|
|
{
|
|
return new Vector3( c1.x - c2.x, c1.y - c2.y, c1.z );
|
|
}
|
|
|
|
|
|
// Vector2Int x Vector4 Operators
|
|
public static Vector4 operator +( Vector2Int c1, Vector4 c2 )
|
|
{
|
|
return new Vector4( c1.x + c2.x, c1.y + c2.y, c2.z, c2.w );
|
|
}
|
|
|
|
public static Vector4 operator +( Vector4 c1, Vector2Int c2 )
|
|
{
|
|
return new Vector4( c1.x + c2.x, c1.y + c2.y, c1.z, c1.w );
|
|
}
|
|
public static Vector4 operator -( Vector2Int c1, Vector4 c2 )
|
|
{
|
|
return new Vector4( c1.x - c2.x, c1.y - c2.y, -c2.z, -c2.w );
|
|
}
|
|
public static Vector4 operator -( Vector4 c1, Vector2Int c2 )
|
|
{
|
|
return new Vector4( c1.x - c2.x, c1.y - c2.y, c1.z, c1.w );
|
|
}
|
|
public static Vector4 operator *( Vector2Int c1, Vector4 c2 )
|
|
{
|
|
return new Vector4( c1.x * c2.x, c1.y * c2.y, c2.z, c2.w );
|
|
}
|
|
public static Vector4 operator *( Vector4 c1, Vector2Int c2 )
|
|
{
|
|
return new Vector4( c1.x * c2.x, c1.y * c2.y, c1.z, c1.w );
|
|
}
|
|
public static Vector4 operator /( Vector2Int c1, Vector4 c2 )
|
|
{
|
|
return new Vector4( c1.x / c2.x, c1.y / c2.y, c2.z, c2.w );
|
|
}
|
|
public static Vector4 operator /( Vector4 c1, Vector2Int c2 )
|
|
{
|
|
return new Vector4( c1.x / c2.x, c1.y / c2.y, c1.z, c1.w );
|
|
}
|
|
|
|
|
|
// Other Operators
|
|
public static Vector2Int operator -( Vector2Int c1 )
|
|
{
|
|
return new Vector2Int( -c1.x, -c1.y );
|
|
}
|
|
|
|
|
|
// Implicit conversions
|
|
static public implicit operator Vector2Int( int value )
|
|
{
|
|
return new Vector2Int( value, value );
|
|
}
|
|
static public implicit operator Vector2( Vector2Int value )
|
|
{
|
|
return new Vector2( value.x, value.y );
|
|
}
|
|
|
|
// Explicit conversions
|
|
static public explicit operator Vector2Int( Vector2 value )
|
|
{
|
|
return new Vector2Int( (int)value.x, (int)value.y );
|
|
}
|
|
static public explicit operator Vector2Int( Vector3 value )
|
|
{
|
|
return new Vector2Int( (int)value.x, (int)value.y );
|
|
}
|
|
|
|
static public explicit operator Vector2Int( Vector4 value )
|
|
{
|
|
return new Vector2Int( (int)value.x, (int)value.y );
|
|
}
|
|
|
|
public int this[int index]
|
|
{
|
|
get
|
|
{
|
|
return index switch
|
|
{
|
|
0 => x,
|
|
1 => y,
|
|
_ => throw new IndexOutOfRangeException(),
|
|
};
|
|
}
|
|
|
|
set
|
|
{
|
|
switch ( index )
|
|
{
|
|
case 0: x = value; break;
|
|
case 1: y = value; break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Length (or magnitude) of the integer vector (Distance from 0,0)
|
|
/// </summary>
|
|
public readonly float Length => MathF.Sqrt( x * x + y * y );
|
|
|
|
/// <summary>
|
|
/// Squared length of the integer vector. This is faster than <see cref="Length">Length</see>, and can be used for things like comparing distances, as long as only squared values are used."/>
|
|
/// </summary>
|
|
public readonly int LengthSquared => x * x + y * y;
|
|
|
|
/// <summary>
|
|
/// Returns an integer vector that runs perpendicular to this one.
|
|
/// </summary>
|
|
public readonly Vector2Int Perpendicular => new Vector2Int( -y, x );
|
|
|
|
/// <summary>
|
|
/// Whether the length of this vector is zero or not.
|
|
/// </summary>
|
|
public readonly bool IsZeroLength => x == 0 && y == 0;
|
|
|
|
/// <summary>
|
|
/// Returns true if value on every axis is less than or equal to tolerance
|
|
/// </summary>
|
|
public readonly bool IsNearlyZero( int tolerance = 0 )
|
|
{
|
|
return Math.Abs( x ) <= tolerance && Math.Abs( y ) <= tolerance;
|
|
}
|
|
|
|
public void Write( BinaryWriter writer )
|
|
{
|
|
writer.Write( x );
|
|
writer.Write( y );
|
|
}
|
|
|
|
public readonly Vector2Int Read( BinaryReader reader )
|
|
{
|
|
return new Vector2Int( reader.ReadInt32(), reader.ReadInt32() );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns an integer vector that has the minimum values on each axis of the two input vectors.
|
|
/// </summary>
|
|
public readonly Vector2Int ComponentMin( Vector2Int other )
|
|
{
|
|
return new Vector2Int( Math.Min( x, other.x ), Math.Min( y, other.y ) );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns an integer vector that has the maximum values on each axis of the two input vectors.
|
|
/// </summary>
|
|
public readonly Vector2Int ComponentMax( Vector2Int other )
|
|
{
|
|
return new Vector2Int( Math.Max( x, other.x ), Math.Max( y, other.y ) );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the distance between this vector and another.
|
|
/// </summary>
|
|
public float Distance( Vector2Int other )
|
|
{
|
|
var dx = other.x - x;
|
|
var dy = other.y - y;
|
|
return MathF.Sqrt( dx * dx + dy * dy );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the distance between this vector and another.
|
|
/// </summary>
|
|
public float Distance( Vector2 other )
|
|
{
|
|
var dx = other.x - x;
|
|
var dy = other.y - y;
|
|
return MathF.Sqrt( dx * dx + dy * dy );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Snap to grid along any of the 2 axes.
|
|
/// </summary>
|
|
public readonly Vector2Int SnapToGrid( int gridSize, bool sx = true, bool sy = true )
|
|
{
|
|
return new Vector2Int(
|
|
sx ? x.SnapToGrid( gridSize ) : x,
|
|
sy ? y.SnapToGrid( gridSize ) : y
|
|
);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns an integer vector that has the minimum values on each axis between 2 given vectors.
|
|
/// </summary>
|
|
public static Vector2Int Min( Vector2Int a, Vector2Int b ) => a.ComponentMin( b );
|
|
|
|
/// <summary>
|
|
/// Returns an integer vector that has the maximum values on each axis between 2 given vectors.
|
|
/// </summary>
|
|
public static Vector2Int Max( Vector2Int a, Vector2Int b ) => a.ComponentMax( b );
|
|
|
|
/// <summary>
|
|
/// Returns a new integer vector with all values positive. -5 becomes 5, ect.
|
|
/// </summary>
|
|
public readonly Vector2Int Abs()
|
|
{
|
|
return new Vector2Int( Math.Abs( x ), Math.Abs( y ) );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns this integer vector with given X component.
|
|
/// </summary>
|
|
public readonly Vector2Int WithX( int x ) => new( x, y );
|
|
|
|
/// <summary>
|
|
/// Returns this integer vector with given Y component.
|
|
/// </summary>
|
|
public readonly Vector2Int WithY( int y ) => new( x, y );
|
|
|
|
#region Equality
|
|
public static bool operator ==( Vector2Int left, Vector2Int right ) => left.Equals( right );
|
|
public static bool operator !=( Vector2Int left, Vector2Int right ) => !(left == right);
|
|
public override bool Equals( object obj ) => obj is Vector2Int o && Equals( o );
|
|
public bool Equals( Vector2Int o ) => x == o.x && y == o.y;
|
|
public override int GetHashCode() => HashCode.Combine( x, y );
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// Given a string, try to convert this into a Vector2Int. Example formatting is "x,y", "[x,y]", "x y", etc.
|
|
/// </summary>
|
|
public static Vector2Int Parse( string str )
|
|
{
|
|
if ( TryParse( str, CultureInfo.InvariantCulture, out var res ) )
|
|
return res;
|
|
|
|
return default;
|
|
}
|
|
|
|
/// <inheritdoc cref="Parse(string)" />
|
|
public static Vector2Int Parse( string str, IFormatProvider provider )
|
|
{
|
|
return Parse( str );
|
|
}
|
|
|
|
/// <inheritdoc cref="Parse(string)" />
|
|
public static bool TryParse( [NotNullWhen( true )] string str, IFormatProvider info, [MaybeNullWhen( false )] out Vector2Int result )
|
|
{
|
|
result = Vector2Int.Zero;
|
|
|
|
if ( string.IsNullOrWhiteSpace( str ) )
|
|
return false;
|
|
|
|
str = str.Trim( '[', ']', ' ', '\n', '\r', '\t', '"' );
|
|
|
|
var components = str.Split( new[] { ' ', ',', ';', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries );
|
|
|
|
if ( components.Length != 2 )
|
|
return false;
|
|
|
|
if ( !int.TryParse( components[0], NumberStyles.Integer, info, out int x ) ||
|
|
!int.TryParse( components[1], NumberStyles.Integer, info, out int y ) )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
result = new Vector2Int( x, y );
|
|
return true;
|
|
}
|
|
}
|