Make math types mutable.

This commit is contained in:
Pieter-Jan Briers
2020-10-12 17:38:24 +02:00
parent 2386fedd25
commit 6102ee80ec
15 changed files with 218 additions and 229 deletions

View File

@@ -8,77 +8,77 @@ namespace Robust.Shared.Maths
/// Uses a right-handed coordinate system. This means that X+ is to the right and Y+ up.
/// </summary>
[Serializable]
public readonly struct Box2 : IEquatable<Box2>
public struct Box2 : IEquatable<Box2>
{
/// <summary>
/// The X coordinate of the left edge of the box.
/// </summary>
public readonly float Left;
public float Left;
/// <summary>
/// The X coordinate of the right edge of the box.
/// </summary>
public readonly float Right;
public float Right;
/// <summary>
/// The Y coordinate of the top edge of the box.
/// </summary>
public readonly float Top;
public float Top;
/// <summary>
/// The Y coordinate of the bottom of the box.
/// </summary>
public readonly float Bottom;
public float Bottom;
public Vector2 BottomRight
public readonly Vector2 BottomRight
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => new Vector2(Right, Bottom);
}
public Vector2 TopLeft
public readonly Vector2 TopLeft
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => new Vector2(Left, Top);
}
public Vector2 TopRight
public readonly Vector2 TopRight
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => new Vector2(Right, Top);
}
public Vector2 BottomLeft
public readonly Vector2 BottomLeft
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => new Vector2(Left, Bottom);
}
public float Width
public readonly float Width
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => MathF.Abs(Right - Left);
}
public float Height
public readonly float Height
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => MathF.Abs(Bottom - Top);
}
public Vector2 Size
public readonly Vector2 Size
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => new Vector2(Width, Height);
}
public Vector2 Center
public readonly Vector2 Center
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => BottomLeft + Size * .5f;
}
public Vector2 Extents
public readonly Vector2 Extents
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => (TopRight - BottomLeft) * 0.5f;
@@ -120,14 +120,14 @@ namespace Robust.Shared.Maths
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Intersects(in Box2 other)
public readonly bool Intersects(in Box2 other)
{
return other.Bottom <= this.Top && other.Top >= this.Bottom && other.Right >= this.Left &&
other.Left <= this.Right;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Box2 Enlarged(float size)
public readonly Box2 Enlarged(float size)
{
return new Box2(Left - size, Bottom - size, Right + size, Top + size);
}
@@ -136,7 +136,7 @@ namespace Robust.Shared.Maths
/// Returns the intersection box created when two Boxes overlap.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Box2 Intersect(in Box2 other)
public readonly Box2 Intersect(in Box2 other)
{
var left = MathF.Max(Left, other.Left);
var right = MathF.Min(Right, other.Right);
@@ -153,7 +153,7 @@ namespace Robust.Shared.Maths
/// Returns how much two Boxes overlap from 0 to 1.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float IntersectPercentage(in Box2 other)
public readonly float IntersectPercentage(in Box2 other)
{
var surfaceIntersect = Area(Intersect(other));
@@ -164,7 +164,7 @@ namespace Robust.Shared.Maths
/// Returns the smallest rectangle that contains both of the rectangles.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Box2 Union(in Box2 other)
public readonly Box2 Union(in Box2 other)
{
var left = MathF.Min(Left, other.Left);
var right = MathF.Max(Right, other.Right);
@@ -178,33 +178,33 @@ namespace Robust.Shared.Maths
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool IsEmpty()
public readonly bool IsEmpty()
{
return MathHelper.CloseTo(Width, 0.0f) && MathHelper.CloseTo(Height, 0.0f);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Encloses(in Box2 inner)
public readonly bool Encloses(in Box2 inner)
{
return this.Left < inner.Left && this.Bottom < inner.Bottom && this.Right > inner.Right &&
this.Top > inner.Top;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Contains(in Box2 inner)
public readonly bool Contains(in Box2 inner)
=> Left <= inner.Left
&& Bottom <= inner.Bottom
&& Right >= inner.Right
&& Top >= inner.Top;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Contains(float x, float y)
public readonly bool Contains(float x, float y)
{
return Contains(new Vector2(x, y));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Contains(Vector2 point, bool closedRegion = true)
public readonly bool Contains(Vector2 point, bool closedRegion = true)
{
var xOk = closedRegion
? point.X >= Left ^ point.X > Right
@@ -223,7 +223,7 @@ namespace Robust.Shared.Maths
/// <param name="scalar">Value to scale the box by.</param>
/// <returns>Scaled box.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Box2 Scale(float scalar)
public readonly Box2 Scale(float scalar)
{
if (scalar < 0)
{
@@ -239,27 +239,27 @@ namespace Robust.Shared.Maths
/// <summary>Returns a Box2 translated by the given amount.</summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Box2 Translated(Vector2 point)
public readonly Box2 Translated(Vector2 point)
{
return new Box2(Left + point.X, Bottom + point.Y, Right + point.X, Top + point.Y);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(Box2 other)
public readonly bool Equals(Box2 other)
{
return Left.Equals(other.Left) && Right.Equals(other.Right) && Top.Equals(other.Top) &&
Bottom.Equals(other.Bottom);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object? obj)
public override readonly bool Equals(object? obj)
{
if (obj is null) return false;
return obj is Box2 box2 && Equals(box2);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode()
public override readonly int GetHashCode()
{
unchecked
{
@@ -315,7 +315,7 @@ namespace Robust.Shared.Maths
/// Returns this box enlarged to also contain the specified position.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Box2 ExtendToContain(Vector2 vec)
public readonly Box2 ExtendToContain(Vector2 vec)
{
var (x, y) = vec;
@@ -329,7 +329,7 @@ namespace Robust.Shared.Maths
/// <summary>
/// Given a point, returns the closest point to it inside the box.
/// </summary>
public Vector2 ClosestPoint(in Vector2 position)
public readonly Vector2 ClosestPoint(in Vector2 position)
{
// clamp the point to the border of the box
var cx = MathHelper.Clamp(position.X, Left, Right);

View File

@@ -6,24 +6,24 @@ namespace Robust.Shared.Maths
/// This type contains a <see cref="Box2"/> and a rotation <see cref="Angle"/> in world space.
/// </summary>
[Serializable]
public readonly struct Box2Rotated : IEquatable<Box2Rotated>
public struct Box2Rotated : IEquatable<Box2Rotated>
{
public readonly Box2 Box;
public readonly Angle Rotation;
public Box2 Box;
public Angle Rotation;
/// <summary>
/// The point about which the rotation occurs.
/// </summary>
public readonly Vector2 Origin;
public Vector2 Origin;
/// <summary>
/// A 1x1 unit box with the origin centered and identity rotation.
/// </summary>
public static readonly Box2Rotated UnitCentered = new Box2Rotated(Box2.UnitCentered, Angle.Zero, Vector2.Zero);
public Vector2 BottomRight => Origin + Rotation.RotateVec(Box.BottomRight - Origin);
public Vector2 TopLeft => Origin + Rotation.RotateVec(Box.TopLeft - Origin);
public Vector2 TopRight => Origin + Rotation.RotateVec(Box.TopRight - Origin);
public Vector2 BottomLeft => Origin + Rotation.RotateVec(Box.BottomLeft - Origin);
public readonly Vector2 BottomRight => Origin + Rotation.RotateVec(Box.BottomRight - Origin);
public readonly Vector2 TopLeft => Origin + Rotation.RotateVec(Box.TopLeft - Origin);
public readonly Vector2 TopRight => Origin + Rotation.RotateVec(Box.TopRight - Origin);
public readonly Vector2 BottomLeft => Origin + Rotation.RotateVec(Box.BottomLeft - Origin);
public Box2Rotated(Vector2 bottomLeft, Vector2 topRight)
: this(new Box2(bottomLeft, topRight)) { }
@@ -44,7 +44,7 @@ namespace Robust.Shared.Maths
/// <summary>
/// calculates the smallest AABB that will encompass the rotated box. The AABB is in local space.
/// </summary>
public Box2 CalcBoundingBox()
public readonly Box2 CalcBoundingBox()
{
// https://stackoverflow.com/a/19830964
@@ -69,20 +69,20 @@ namespace Robust.Shared.Maths
#region Equality
/// <inheritdoc />
public bool Equals(Box2Rotated other)
public readonly bool Equals(Box2Rotated other)
{
return Box.Equals(other.Box) && Rotation.Equals(other.Rotation);
}
/// <inheritdoc />
public override bool Equals(object? obj)
public override readonly bool Equals(object? obj)
{
if (ReferenceEquals(null, obj)) return false;
return obj is Box2Rotated other && Equals(other);
}
/// <inheritdoc />
public override int GetHashCode()
public override readonly int GetHashCode()
{
unchecked
{
@@ -111,7 +111,7 @@ namespace Robust.Shared.Maths
/// <summary>
/// Returns a string representation of this type.
/// </summary>
public override string ToString()
public override readonly string ToString()
{
return $"{Box.ToString()}, {Rotation.ToString()}";
}

View File

@@ -3,20 +3,20 @@
namespace Robust.Shared.Maths
{
[Serializable]
public readonly struct Box2i : IEquatable<Box2i>
public struct Box2i : IEquatable<Box2i>
{
public readonly int Left;
public readonly int Right;
public readonly int Top;
public readonly int Bottom;
public int Left;
public int Right;
public int Top;
public int Bottom;
public Vector2i BottomRight => new Vector2i(Right, Bottom);
public Vector2i TopLeft => new Vector2i(Left, Top);
public Vector2i TopRight => new Vector2i(Right, Top);
public Vector2i BottomLeft => new Vector2i(Left, Bottom);
public int Width => Math.Abs(Right - Left);
public int Height => Math.Abs(Top - Bottom);
public Vector2i Size => new Vector2i(Width, Height);
public readonly Vector2i BottomRight => new Vector2i(Right, Bottom);
public readonly Vector2i TopLeft => new Vector2i(Left, Top);
public readonly Vector2i TopRight => new Vector2i(Right, Top);
public readonly Vector2i BottomLeft => new Vector2i(Left, Bottom);
public readonly int Width => Math.Abs(Right - Left);
public readonly int Height => Math.Abs(Top - Bottom);
public readonly Vector2i Size => new Vector2i(Width, Height);
public Box2i(Vector2i bottomLeft, Vector2i topRight) : this(bottomLeft.X, bottomLeft.Y, topRight.X, topRight.Y)
{
@@ -40,12 +40,12 @@ namespace Robust.Shared.Maths
return FromDimensions(position.X, position.Y, size.X, size.Y);
}
public bool Contains(int x, int y)
public readonly bool Contains(int x, int y)
{
return Contains(new Vector2i(x, y));
}
public bool Contains(Vector2i point, bool closedRegion = true)
public readonly bool Contains(Vector2i point, bool closedRegion = true)
{
var xOk = closedRegion
? point.X >= Left ^ point.X > Right
@@ -57,7 +57,7 @@ namespace Robust.Shared.Maths
}
/// <summary>Returns a UIBox2 translated by the given amount.</summary>
public Box2i Translated(Vector2i point)
public readonly Box2i Translated(Vector2i point)
{
return new Box2i(Left + point.X, Bottom + point.Y, Right + point.X, Top + point.Y);
}
@@ -65,7 +65,7 @@ namespace Robust.Shared.Maths
/// <summary>
/// Returns the smallest rectangle that contains both of the rectangles.
/// </summary>
public Box2i Union(in Box2i other)
public readonly Box2i Union(in Box2i other)
{
var left = Math.Min(Left, other.Left);
var right = Math.Max(Right, other.Right);
@@ -79,7 +79,7 @@ namespace Robust.Shared.Maths
}
// override object.Equals
public override bool Equals(object? obj)
public override readonly bool Equals(object? obj)
{
if (obj is Box2i box)
{
@@ -89,13 +89,13 @@ namespace Robust.Shared.Maths
return false;
}
public bool Equals(Box2i other)
public readonly bool Equals(Box2i other)
{
return other.Left == Left && other.Right == Right && other.Bottom == Bottom && other.Top == Top;
}
// override object.GetHashCode
public override int GetHashCode()
public override readonly int GetHashCode()
{
var code = Left.GetHashCode();
code = (code * 929) ^ Right.GetHashCode();
@@ -114,7 +114,7 @@ namespace Robust.Shared.Maths
return new Box2(box.Left, box.Bottom, box.Right, box.Top);
}
public override string ToString()
public override readonly string ToString()
{
return $"({Left}, {Bottom}, {Right}, {Top})";
}

View File

@@ -6,17 +6,17 @@ namespace Robust.Shared.Maths
/// Represents a circle with a 2D position and a radius.
/// </summary>
[Serializable]
public readonly struct Circle : IEquatable<Circle>
public struct Circle : IEquatable<Circle>
{
/// <summary>
/// Position of the circle in 2D space.
/// </summary>
public readonly Vector2 Position;
public Vector2 Position;
/// <summary>
/// Radius of the circle.
/// </summary>
public readonly float Radius;
public float Radius;
/// <summary>
/// Constructs an instance of this struct.
@@ -30,7 +30,7 @@ namespace Robust.Shared.Maths
/// <summary>
/// Checks if this circle contains a point.
/// </summary>
public bool Contains(Vector2 point)
public readonly bool Contains(Vector2 point)
{
return Contains(point.X, point.Y);
}
@@ -38,7 +38,7 @@ namespace Robust.Shared.Maths
/// <summary>
/// Checks if this circle intersects with another circle.
/// </summary>
public bool Intersects(Circle circle)
public readonly bool Intersects(Circle circle)
{
var dx = Position.X - circle.Position.X;
var dy = Position.Y - circle.Position.Y;
@@ -50,7 +50,7 @@ namespace Robust.Shared.Maths
/// <summary>
/// Checks if this circle intersects with a box.
/// </summary>
public bool Intersects(Box2 box)
public readonly bool Intersects(Box2 box)
{
// Construct the point in / on the box nearest to the center of the circle.
float closestX = MathHelper.Median(box.Left, box.Right, Position.X);
@@ -60,7 +60,7 @@ namespace Robust.Shared.Maths
return Contains(closestX, closestY);
}
private bool Contains(float x, float y)
private readonly bool Contains(float x, float y)
{
var dx = Position.X - x;
var dy = Position.Y - y;
@@ -73,20 +73,20 @@ namespace Robust.Shared.Maths
}
/// <inheritdoc />
public bool Equals(Circle other)
public readonly bool Equals(Circle other)
{
return Position.Equals(other.Position) && Radius.Equals(other.Radius);
}
/// <inheritdoc />
public override bool Equals(object? obj)
public override readonly bool Equals(object? obj)
{
if (ReferenceEquals(null, obj)) return false;
return obj is Circle circle && Equals(circle);
}
/// <inheritdoc />
public override int GetHashCode()
public override readonly int GetHashCode()
{
unchecked
{
@@ -104,7 +104,7 @@ namespace Robust.Shared.Maths
return !(a == b);
}
public override string ToString()
public override readonly string ToString()
{
return $"Circle ({Position.X}, {Position.Y}), {Radius} r";
}

View File

@@ -43,32 +43,32 @@ namespace Robust.Shared.Maths
/// Represents a color with 4 floating-point components (R, G, B, A).
/// </summary>
[Serializable]
public readonly struct Color : IEquatable<Color>
public struct Color : IEquatable<Color>
{
/// <summary>
/// The red component of this Color4 structure.
/// </summary>
public readonly float R;
public float R;
/// <summary>
/// The green component of this Color4 structure.
/// </summary>
public readonly float G;
public float G;
/// <summary>
/// The blue component of this Color4 structure.
/// </summary>
public readonly float B;
public float B;
/// <summary>
/// The alpha component of this Color4 structure.
/// </summary>
public readonly float A;
public float A;
public byte RByte => (byte) (R * byte.MaxValue);
public byte GByte => (byte) (G * byte.MaxValue);
public byte BByte => (byte) (B * byte.MaxValue);
public byte AByte => (byte) (A * byte.MaxValue);
public readonly byte RByte => (byte) (R * byte.MaxValue);
public readonly byte GByte => (byte) (G * byte.MaxValue);
public readonly byte BByte => (byte) (B * byte.MaxValue);
public readonly byte AByte => (byte) (A * byte.MaxValue);
/// <summary>
/// Constructs a new Color4 structure from the specified components.
@@ -108,7 +108,7 @@ namespace Robust.Shared.Maths
/// This method is intended only for compatibility with System.Drawing. It compresses the color into 8 bits per
/// channel, which means color information is lost.
/// </remarks>
public int ToArgb()
public readonly int ToArgb()
{
var value =
((uint) (A * byte.MaxValue) << 24) |
@@ -161,7 +161,7 @@ namespace Robust.Shared.Maths
return new Color(tuple.r, tuple.g, tuple.b);
}
public void Deconstruct(out float r, out float g, out float b, out float a)
public readonly void Deconstruct(out float r, out float g, out float b, out float a)
{
r = R;
g = G;
@@ -169,7 +169,7 @@ namespace Robust.Shared.Maths
a = A;
}
public void Deconstruct(out float r, out float g, out float b)
public readonly void Deconstruct(out float r, out float g, out float b)
{
r = R;
g = G;
@@ -210,7 +210,7 @@ namespace Robust.Shared.Maths
/// </summary>
/// <param name="obj">An object to compare to.</param>
/// <returns>True obj is a Color4 structure with the same components as this Color4; false otherwise.</returns>
public override bool Equals(object? obj)
public override readonly bool Equals(object? obj)
{
if (!(obj is Color))
return false;
@@ -222,7 +222,7 @@ namespace Robust.Shared.Maths
/// Calculates the hash code for this Color4 structure.
/// </summary>
/// <returns>A System.Int32 containing the hash code of this Color4 structure.</returns>
public override int GetHashCode()
public override readonly int GetHashCode()
{
return ToArgb();
}
@@ -231,47 +231,47 @@ namespace Robust.Shared.Maths
/// Creates a System.String that describes this Color4 structure.
/// </summary>
/// <returns>A System.String that describes this Color4 structure.</returns>
public override string ToString()
public override readonly string ToString()
{
return $"{{(R, G, B, A) = ({R}, {G}, {B}, {A})}}";
}
public Color WithRed(float newR)
public readonly Color WithRed(float newR)
{
return new Color(newR, G, B, A);
}
public Color WithGreen(float newG)
public readonly Color WithGreen(float newG)
{
return new Color(R, newG, B, A);
}
public Color WithBlue(float newB)
public readonly Color WithBlue(float newB)
{
return new Color(R, G, newB, A);
}
public Color WithAlpha(float newA)
public readonly Color WithAlpha(float newA)
{
return new Color(R, G, B, newA);
}
public Color WithRed(byte newR)
public readonly Color WithRed(byte newR)
{
return new Color((float) newR / byte.MaxValue, G, B, A);
}
public Color WithGreen(byte newG)
public readonly Color WithGreen(byte newG)
{
return new Color(R, (float) newG / byte.MaxValue, B, A);
}
public Color WithBlue(byte newB)
public readonly Color WithBlue(byte newB)
{
return new Color(R, G, (float) newB / byte.MaxValue, A);
}
public Color WithAlpha(byte newA)
public readonly Color WithAlpha(byte newA)
{
return new Color(R, G, B, (float) newA / byte.MaxValue);
}
@@ -973,7 +973,7 @@ namespace Robust.Shared.Maths
return new Color(a.R * b.R, a.G * b.G, a.B * b.B, a.A * b.A);
}
public string ToHex()
public readonly string ToHex()
{
var hexColor = 0;
hexColor += RByte << 24;
@@ -984,7 +984,7 @@ namespace Robust.Shared.Maths
return $"#{hexColor:X8}";
}
public string ToHexNoAlpha()
public readonly string ToHexNoAlpha()
{
var hexColor = 0;
hexColor += RByte << 16;
@@ -999,7 +999,7 @@ namespace Robust.Shared.Maths
/// </summary>
/// <param name="other">The Color4 structure to compare to.</param>
/// <returns>True if both Color4 structures contain the same components; false otherwise.</returns>
public bool Equals(Color other)
public readonly bool Equals(Color other)
{
return
MathHelper.CloseTo(R, other.R) &&
@@ -1880,7 +1880,7 @@ namespace Robust.Shared.Maths
private static readonly Dictionary<Color, string> DefaultColorsInverted =
DefaultColors.ToLookup(pair => pair.Value).ToDictionary(i => i.Key, i => i.First().Key);
public string? Name()
public readonly string? Name()
{
return DefaultColorsInverted.TryGetValue(this, out var name) ? name : null;
}

View File

@@ -7,36 +7,36 @@ namespace Robust.Shared.Maths
/// Uses a left-handed coordinate system. This means that X+ is to the right and Y+ down.
/// </summary>
[Serializable]
public readonly struct UIBox2 : IEquatable<UIBox2>
public struct UIBox2 : IEquatable<UIBox2>
{
/// <summary>
/// The X coordinate of the left edge of the box.
/// </summary>
public readonly float Left;
public float Left;
/// <summary>
/// The X coordinate of the right edge of the box.
/// </summary>
public readonly float Right;
public float Right;
/// <summary>
/// The Y coordinate of the top edge of the box.
/// </summary>
public readonly float Top;
public float Top;
/// <summary>
/// The Y coordinate of the bottom of the box.
/// </summary>
public readonly float Bottom;
public float Bottom;
public Vector2 BottomRight => new Vector2(Right, Bottom);
public Vector2 TopLeft => new Vector2(Left, Top);
public Vector2 TopRight => new Vector2(Right, Top);
public Vector2 BottomLeft => new Vector2(Left, Bottom);
public float Width => MathF.Abs(Right - Left);
public float Height => MathF.Abs(Top - Bottom);
public Vector2 Size => new Vector2(Width, Height);
public Vector2 Center => TopLeft + Size / 2;
public readonly Vector2 BottomRight => new Vector2(Right, Bottom);
public readonly Vector2 TopLeft => new Vector2(Left, Top);
public readonly Vector2 TopRight => new Vector2(Right, Top);
public readonly Vector2 BottomLeft => new Vector2(Left, Bottom);
public readonly float Width => MathF.Abs(Right - Left);
public readonly float Height => MathF.Abs(Top - Bottom);
public readonly Vector2 Size => new Vector2(Width, Height);
public readonly Vector2 Center => TopLeft + Size / 2;
public UIBox2(Vector2 leftTop, Vector2 rightBottom) : this(leftTop.X, leftTop.Y, rightBottom.X, rightBottom.Y)
{
@@ -60,29 +60,29 @@ namespace Robust.Shared.Maths
return FromDimensions(leftTopPosition.X, leftTopPosition.Y, size.X, size.Y);
}
public bool Intersects(UIBox2 other)
public readonly bool Intersects(UIBox2 other)
{
return other.Bottom >= this.Top && other.Top <= this.Bottom && other.Right >= this.Left &&
other.Left <= this.Right;
}
public bool IsEmpty()
public readonly bool IsEmpty()
{
return MathHelper.CloseTo(Width, 0.0f) && MathHelper.CloseTo(Height, 0.0f);
}
public bool Encloses(UIBox2 inner)
public readonly bool Encloses(UIBox2 inner)
{
return this.Left < inner.Left && this.Bottom > inner.Bottom && this.Right > inner.Right &&
this.Top < inner.Top;
}
public bool Contains(float x, float y)
public readonly bool Contains(float x, float y)
{
return Contains(new Vector2(x, y));
}
public bool Contains(Vector2 point, bool closedRegion = true)
public readonly bool Contains(Vector2 point, bool closedRegion = true)
{
var xOk = closedRegion
? point.X >= Left ^ point.X > Right
@@ -100,7 +100,7 @@ namespace Robust.Shared.Maths
/// </summary>
/// <param name="scalar">Value to scale the box by.</param>
/// <returns>Scaled box.</returns>
public UIBox2 Scale(float scalar)
public readonly UIBox2 Scale(float scalar)
{
if (scalar < 0)
{
@@ -115,24 +115,24 @@ namespace Robust.Shared.Maths
}
/// <summary>Returns a UIBox2 translated by the given amount.</summary>
public UIBox2 Translated(Vector2 point)
public readonly UIBox2 Translated(Vector2 point)
{
return new UIBox2(Left + point.X, Top + point.Y, Right + point.X, Bottom + point.Y);
}
public bool Equals(UIBox2 other)
public readonly bool Equals(UIBox2 other)
{
return Left.Equals(other.Left) && Right.Equals(other.Right) && Top.Equals(other.Top) &&
Bottom.Equals(other.Bottom);
}
public override bool Equals(object? obj)
public override readonly bool Equals(object? obj)
{
if (obj is null) return false;
return obj is UIBox2 box2 && Equals(box2);
}
public override int GetHashCode()
public override readonly int GetHashCode()
{
unchecked
{
@@ -167,7 +167,7 @@ namespace Robust.Shared.Maths
return new UIBox2(box.Left + lo, box.Top + to, box.Right + ro, box.Bottom + bo);
}
public override string ToString()
public override readonly string ToString()
{
return $"({Left}, {Top}, {Right}, {Bottom})";
}

View File

@@ -3,20 +3,20 @@
namespace Robust.Shared.Maths
{
[Serializable]
public readonly struct UIBox2i : IEquatable<UIBox2i>
public struct UIBox2i : IEquatable<UIBox2i>
{
public readonly int Left;
public readonly int Right;
public readonly int Top;
public readonly int Bottom;
public int Left;
public int Right;
public int Top;
public int Bottom;
public Vector2i BottomRight => new Vector2i(Right, Bottom);
public Vector2i TopLeft => new Vector2i(Left, Top);
public Vector2i TopRight => new Vector2i(Right, Top);
public Vector2i BottomLeft => new Vector2i(Left, Bottom);
public int Width => Math.Abs(Right - Left);
public int Height => Math.Abs(Top - Bottom);
public Vector2i Size => new Vector2i(Width, Height);
public readonly Vector2i BottomRight => new Vector2i(Right, Bottom);
public readonly Vector2i TopLeft => new Vector2i(Left, Top);
public readonly Vector2i TopRight => new Vector2i(Right, Top);
public readonly Vector2i BottomLeft => new Vector2i(Left, Bottom);
public readonly int Width => Math.Abs(Right - Left);
public readonly int Height => Math.Abs(Top - Bottom);
public readonly Vector2i Size => new Vector2i(Width, Height);
public UIBox2i(Vector2i topLeft, Vector2i bottomRight) : this(topLeft.X, topLeft.Y, bottomRight.X, bottomRight.Y)
{
@@ -40,12 +40,12 @@ namespace Robust.Shared.Maths
return FromDimensions(position.X, position.Y, size.X, size.Y);
}
public bool Contains(int x, int y)
public readonly bool Contains(int x, int y)
{
return Contains(new Vector2i(x, y));
}
public bool Contains(Vector2i point, bool closedRegion = true)
public readonly bool Contains(Vector2i point, bool closedRegion = true)
{
var xOk = closedRegion
? point.X >= Left ^ point.X > Right
@@ -57,7 +57,7 @@ namespace Robust.Shared.Maths
}
/// <summary>Returns a UIBox2 translated by the given amount.</summary>
public UIBox2i Translated(Vector2i point)
public readonly UIBox2i Translated(Vector2i point)
{
return new UIBox2i(Left + point.X, Top + point.Y, Right + point.X, Bottom + point.Y);
}
@@ -70,7 +70,7 @@ namespace Robust.Shared.Maths
/// <returns>
/// <c>null</c> if there is no intersection, otherwise the smallest region that fits in both boxes.
/// </returns>
public UIBox2i? Intersection(in UIBox2i other)
public readonly UIBox2i? Intersection(in UIBox2i other)
{
if (!Intersects(other))
{
@@ -81,14 +81,14 @@ namespace Robust.Shared.Maths
Vector2i.ComponentMin(BottomRight, other.BottomRight));
}
public bool Intersects(in UIBox2i other)
public readonly bool Intersects(in UIBox2i other)
{
return other.Bottom >= this.Top && other.Top <= this.Bottom && other.Right >= this.Left &&
other.Left <= this.Right;
}
// override object.Equals
public override bool Equals(object? obj)
public override readonly bool Equals(object? obj)
{
if (obj is UIBox2i box)
{
@@ -98,13 +98,13 @@ namespace Robust.Shared.Maths
return false;
}
public bool Equals(UIBox2i other)
public readonly bool Equals(UIBox2i other)
{
return other.Left == Left && other.Right == Right && other.Bottom == Bottom && other.Top == Top;
}
// override object.GetHashCode
public override int GetHashCode()
public override readonly int GetHashCode()
{
var code = Left.GetHashCode();
code = (code * 929) ^ Right.GetHashCode();
@@ -130,7 +130,7 @@ namespace Robust.Shared.Maths
return new UIBox2i(box.Left + lo, box.Top + to, box.Right + ro, box.Bottom + bo);
}
public override string ToString()
public override readonly string ToString()
{
return $"({Left}, {Top}, {Right}, {Bottom})";
}

View File

@@ -9,17 +9,17 @@ namespace Robust.Shared.Maths
/// </summary>
[StructLayout(LayoutKind.Sequential)]
[Serializable]
public readonly struct Vector2 : IEquatable<Vector2>, IApproxEquatable<Vector2>
public struct Vector2 : IEquatable<Vector2>, IApproxEquatable<Vector2>
{
/// <summary>
/// The X component of the vector.
/// </summary>
public readonly float X;
public float X;
/// <summary>
/// The Y component of the vector.
/// </summary>
public readonly float Y;
public float Y;
/// <summary>
/// A zero length vector.
@@ -56,7 +56,7 @@ namespace Robust.Shared.Maths
/// <summary>
/// Gets the length (magnitude) of the vector.
/// </summary>
public float Length
public readonly float Length
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => MathF.Sqrt(LengthSquared);
@@ -65,7 +65,7 @@ namespace Robust.Shared.Maths
/// <summary>
/// Gets the squared length of the vector.
/// </summary>
public float LengthSquared
public readonly float LengthSquared
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => X * X + Y * Y;
@@ -75,7 +75,7 @@ namespace Robust.Shared.Maths
/// Returns a new, normalized, vector.
/// </summary>
/// <returns></returns>
public Vector2 Normalized
public readonly Vector2 Normalized
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
@@ -86,7 +86,7 @@ namespace Robust.Shared.Maths
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector2 Rounded()
public readonly Vector2 Rounded()
{
return new Vector2((float) MathF.Round(X), (float) MathF.Round(Y));
}
@@ -316,7 +316,7 @@ namespace Robust.Shared.Maths
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Deconstruct(out float x, out float y)
public readonly void Deconstruct(out float x, out float y)
{
x = X;
y = Y;
@@ -332,7 +332,7 @@ namespace Robust.Shared.Maths
/// <summary>
/// Returns a string that represents the current Vector2.
/// </summary>
public override string ToString()
public override readonly string ToString()
{
return $"({X}, {Y})";
}
@@ -355,7 +355,7 @@ namespace Robust.Shared.Maths
/// <param name="other">Other vector to check.</param>
/// <returns>True if the two vectors are equal.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(Vector2 other)
public readonly bool Equals(Vector2 other)
{
// ReSharper disable CompareOfFloatsByEqualityOperator
return X == other.X && Y == other.Y;
@@ -368,7 +368,7 @@ namespace Robust.Shared.Maths
/// <param name="obj">Other object to check.</param>
/// <returns>True if Object and vector are equal.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object? obj)
public override readonly bool Equals(object? obj)
{
return obj is Vector2 vec && Equals(vec);
}
@@ -378,7 +378,7 @@ namespace Robust.Shared.Maths
/// </summary>
/// <returns>A unique hash code for this instance.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode()
public override readonly int GetHashCode()
{
unchecked
{
@@ -387,13 +387,13 @@ namespace Robust.Shared.Maths
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool EqualsApprox(Vector2 other)
public readonly bool EqualsApprox(Vector2 other)
{
return MathHelper.CloseTo(X, other.X) && MathHelper.CloseTo(Y, other.Y);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool EqualsApprox(Vector2 other, double tolerance)
public readonly bool EqualsApprox(Vector2 other, double tolerance)
{
return MathHelper.CloseTo(X, other.X, tolerance) && MathHelper.CloseTo(Y, other.Y, tolerance);
}

View File

@@ -5,10 +5,10 @@ namespace Robust.Shared.Maths
{
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public readonly struct Vector2d
public struct Vector2d
{
public readonly double X;
public readonly double Y;
public double X;
public double Y;
public Vector2d(double x, double y)
{
@@ -16,7 +16,7 @@ namespace Robust.Shared.Maths
Y = y;
}
public void Deconstruct(out double x, out double y)
public readonly void Deconstruct(out double x, out double y)
{
x = X;
y = Y;

View File

@@ -8,7 +8,7 @@ namespace Robust.Shared.Maths
[Serializable]
[StructLayout(LayoutKind.Sequential)]
// ReSharper disable once InconsistentNaming
public readonly struct Vector2i : IEquatable<Vector2i>
public struct Vector2i : IEquatable<Vector2i>
{
public static readonly Vector2i Zero = (0, 0);
public static readonly Vector2i One = (1, 1);
@@ -16,12 +16,12 @@ namespace Robust.Shared.Maths
/// <summary>
/// The X component of the Vector2i.
/// </summary>
public readonly int X;
public int X;
/// <summary>
/// The Y component of the Vector2i.
/// </summary>
public readonly int Y;
public int Y;
/// <summary>
/// Construct a vector from its coordinates.
@@ -49,7 +49,7 @@ namespace Robust.Shared.Maths
/// </summary>
/// <param name="other">Other vector to check.</param>
/// <returns>True if the two vectors are equal.</returns>
public bool Equals(Vector2i other)
public readonly bool Equals(Vector2i other)
{
return X == other.X && Y == other.Y;
}
@@ -59,7 +59,7 @@ namespace Robust.Shared.Maths
/// </summary>
/// <param name="obj">Other object to check.</param>
/// <returns>True if Object and vector are equal.</returns>
public override bool Equals(object? obj)
public override readonly bool Equals(object? obj)
{
if (ReferenceEquals(null, obj)) return false;
return obj is Vector2i vector && Equals(vector);
@@ -69,7 +69,7 @@ namespace Robust.Shared.Maths
/// Returns the hash code for this instance.
/// </summary>
/// <returns>A unique hash code for this instance.</returns>
public override int GetHashCode()
public override readonly int GetHashCode()
{
unchecked
{
@@ -142,7 +142,7 @@ namespace Robust.Shared.Maths
return !a.Equals(b);
}
public void Deconstruct(out int x, out int y)
public readonly void Deconstruct(out int x, out int y)
{
x = X;
y = Y;
@@ -167,7 +167,7 @@ namespace Robust.Shared.Maths
/// <summary>
/// Returns a string that represents the current Vector2i.
/// </summary>
public override string ToString()
public override readonly string ToString()
{
return $"({X}, {Y})";
}

View File

@@ -7,17 +7,17 @@ namespace Robust.Shared.Maths
[JsonObject(MemberSerialization.Fields)]
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public readonly struct Vector2u : IEquatable<Vector2u>
public struct Vector2u : IEquatable<Vector2u>
{
/// <summary>
/// The X component of the Vector2i.
/// </summary>
public readonly uint X;
public uint X;
/// <summary>
/// The Y component of the Vector2i.
/// </summary>
public readonly uint Y;
public uint Y;
/// <summary>
/// Construct a vector from its coordinates.
@@ -30,7 +30,7 @@ namespace Robust.Shared.Maths
Y = y;
}
public void Deconstruct(out uint x, out uint y)
public readonly void Deconstruct(out uint x, out uint y)
{
x = X;
y = Y;
@@ -41,7 +41,7 @@ namespace Robust.Shared.Maths
/// </summary>
/// <param name="other">Other vector to check.</param>
/// <returns>True if the two vectors are equal.</returns>
public bool Equals(Vector2u other)
public readonly bool Equals(Vector2u other)
{
return X == other.X && Y == other.Y;
}
@@ -51,7 +51,7 @@ namespace Robust.Shared.Maths
/// </summary>
/// <param name="obj">Other object to check.</param>
/// <returns>True if Object and vector are equal.</returns>
public override bool Equals(object? obj)
public override readonly bool Equals(object? obj)
{
if (ReferenceEquals(null, obj)) return false;
return obj is Vector2u vec && Equals(vec);
@@ -61,7 +61,7 @@ namespace Robust.Shared.Maths
/// Returns the hash code for this instance.
/// </summary>
/// <returns>A unique hash code for this instance.</returns>
public override int GetHashCode()
public override readonly int GetHashCode()
{
unchecked
{

View File

@@ -5,11 +5,11 @@ namespace Robust.Shared.Maths
{
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public readonly struct Vector3d
public struct Vector3d
{
public readonly double X;
public readonly double Y;
public readonly double Z;
public double X;
public double Y;
public double Z;
public Vector3d(double x, double y, double z)
{
@@ -18,7 +18,7 @@ namespace Robust.Shared.Maths
Z = z;
}
public void Deconstruct(out double x, out double y, out double z)
public readonly void Deconstruct(out double x, out double y, out double z)
{
x = X;
y = Y;

View File

@@ -5,12 +5,12 @@ namespace Robust.Shared.Maths
{
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public readonly struct Vector4d
public struct Vector4d
{
public readonly double X;
public readonly double Y;
public readonly double Z;
public readonly double W;
public double X;
public double Y;
public double Z;
public double W;
public Vector4d(double x, double y, double z, double w)
{
@@ -20,7 +20,7 @@ namespace Robust.Shared.Maths
W = w;
}
public void Deconstruct(out double x, out double y, out double z, out double w)
public readonly void Deconstruct(out double x, out double y, out double z, out double w)
{
x = X;
y = Y;

View File

@@ -304,32 +304,24 @@ namespace Robust.Shared.Physics
// Predict AABB movement
var d = displacement * AabbMultiplier;
// pls can we make math types mutable this sucks.
var l = fatAabb.Left;
var b = fatAabb.Bottom;
var r = fatAabb.Right;
var t = fatAabb.Top;
if (d.X < 0)
{
l += d.X;
fatAabb.Left += d.X;
}
else
{
r += d.X;
fatAabb.Right += d.X;
}
if (d.Y < 0)
{
b += d.Y;
fatAabb.Bottom += d.Y;
}
else
{
t += d.Y;
fatAabb.Top += d.Y;
}
fatAabb = new Box2(l, b, r, t);
ref var treeAabb = ref leafNode.Aabb;
if (treeAabb.Contains(aabb))

View File

@@ -8,20 +8,17 @@ namespace Robust.Shared.Maths
/// A representation of a 2D ray.
/// </summary>
[Serializable]
public readonly struct Ray : IEquatable<Ray>
public struct Ray : IEquatable<Ray>
{
private readonly Vector2 _position;
private readonly Vector2 _direction;
/// <summary>
/// Specifies the starting point of the ray.
/// </summary>
public Vector2 Position => _position;
public Vector2 Position;
/// <summary>
/// Specifies the direction the ray is pointing.
/// </summary>
public Vector2 Direction => _direction;
public Vector2 Direction;
/// <summary>
/// Creates a new instance of a Ray.
@@ -30,16 +27,16 @@ namespace Robust.Shared.Maths
/// <param name="direction">Unit direction vector that the ray is pointing.</param>
public Ray(Vector2 position, Vector2 direction)
{
_position = position;
_direction = direction;
Position = position;
Direction = direction;
DebugTools.Assert(MathHelper.CloseTo(_direction.LengthSquared, 1));
DebugTools.Assert(MathHelper.CloseTo(Direction.LengthSquared, 1));
}
#region Intersect Tests
public bool Intersects(Box2 box, out float distance, out Vector2 hitPos)
public readonly bool Intersects(Box2 box, out float distance, out Vector2 hitPos)
{
hitPos = Vector2.Zero;
distance = 0;
@@ -50,19 +47,19 @@ namespace Robust.Shared.Maths
// X axis slab
{
if (MathF.Abs(_direction.X) < epsilon)
if (MathF.Abs(Direction.X) < epsilon)
{
// ray is parallel to this slab, it will never hit unless ray is inside box
if (_position.X < MathF.Min(box.Left, box.Right) || _position.X > MathF.Max(box.Left, box.Right))
if (Position.X < MathF.Min(box.Left, box.Right) || Position.X > MathF.Max(box.Left, box.Right))
{
return false;
}
}
// calculate intersection t value of ray with near and far plane of slab
var ood = 1.0f / _direction.X;
var t1 = (MathF.Min(box.Left, box.Right) - _position.X) * ood;
var t2 = (MathF.Max(box.Left, box.Right) - _position.X) * ood;
var ood = 1.0f / Direction.X;
var t1 = (MathF.Min(box.Left, box.Right) - Position.X) * ood;
var t2 = (MathF.Max(box.Left, box.Right) - Position.X) * ood;
// Make t1 be the intersection with near plane, t2 with far plane
if (t1 > t2)
@@ -81,19 +78,19 @@ namespace Robust.Shared.Maths
// Y axis slab
{
if (MathF.Abs(_direction.Y) < epsilon)
if (MathF.Abs(Direction.Y) < epsilon)
{
// ray is parallel to this slab, it will never hit unless ray is inside box
if (_position.Y < MathF.Min(box.Top, box.Bottom) || _position.Y > MathF.Max(box.Top, box.Bottom))
if (Position.Y < MathF.Min(box.Top, box.Bottom) || Position.Y > MathF.Max(box.Top, box.Bottom))
{
return false;
}
}
// calculate intersection t value of ray with near and far plane of slab
var ood = 1.0f / _direction.Y;
var t1 = (MathF.Min(box.Top, box.Bottom) - _position.Y) * ood;
var t2 = (MathF.Max(box.Top, box.Bottom) - _position.Y) * ood;
var ood = 1.0f / Direction.Y;
var t1 = (MathF.Min(box.Top, box.Bottom) - Position.Y) * ood;
var t2 = (MathF.Max(box.Top, box.Bottom) - Position.Y) * ood;
// Make t1 be the intersection with near plane, t2 with far plane
if (t1 > t2)
@@ -111,7 +108,7 @@ namespace Robust.Shared.Maths
}
// Ray intersects all slabs. Return point and intersection t value
hitPos = _position + _direction * tmin;
hitPos = Position + Direction * tmin;
distance = tmin;
return true;
}
@@ -124,16 +121,16 @@ namespace Robust.Shared.Maths
/// Determines if this Ray and another Ray are equivalent.
/// </summary>
/// <param name="other">Ray to compare to.</param>
public bool Equals(Ray other)
public readonly bool Equals(Ray other)
{
return _position.Equals(other._position) && _direction.Equals(other._direction);
return Position.Equals(other.Position) && Direction.Equals(other.Direction);
}
/// <summary>
/// Determines if this ray and another object is equivalent.
/// </summary>
/// <param name="obj">Object to compare to.</param>
public override bool Equals(object? obj)
public override readonly bool Equals(object? obj)
{
if (obj is null) return false;
return obj is Ray ray && Equals(ray);
@@ -142,11 +139,11 @@ namespace Robust.Shared.Maths
/// <summary>
/// Calculates the hash code of this Ray.
/// </summary>
public override int GetHashCode()
public override readonly int GetHashCode()
{
unchecked
{
return (_position.GetHashCode() * 397) ^ _direction.GetHashCode();
return (Position.GetHashCode() * 397) ^ Direction.GetHashCode();
}
}