Make [UI]Box2[i] unions with their primary corners as fields.

This uses .NET 5's new Unsafe.SkipInit() function and a lot of FieldOffset.

The result of this is that you can now take a `ref` to the primary corners of the boxes, as well as better codegen in some cases.
This commit is contained in:
Pieter-Jan Briers
2020-11-26 02:00:05 +01:00
parent bf197ce04b
commit 3767a7d285
4 changed files with 80 additions and 50 deletions

View File

@@ -1,5 +1,6 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Robust.Shared.Maths
{
@@ -8,27 +9,31 @@ namespace Robust.Shared.Maths
/// Uses a right-handed coordinate system. This means that X+ is to the right and Y+ up.
/// </summary>
[Serializable]
[StructLayout(LayoutKind.Explicit)]
public struct Box2 : IEquatable<Box2>
{
/// <summary>
/// The X coordinate of the left edge of the box.
/// </summary>
public float Left;
/// <summary>
/// The X coordinate of the right edge of the box.
/// </summary>
public float Right;
/// <summary>
/// The Y coordinate of the top edge of the box.
/// </summary>
public float Top;
[FieldOffset(sizeof(float) * 0)] public float Left;
/// <summary>
/// The Y coordinate of the bottom of the box.
/// </summary>
public float Bottom;
[FieldOffset(sizeof(float) * 1)] public float Bottom;
/// <summary>
/// The X coordinate of the right edge of the box.
/// </summary>
[FieldOffset(sizeof(float) * 2)] public float Right;
/// <summary>
/// The Y coordinate of the top edge of the box.
/// </summary>
[FieldOffset(sizeof(float) * 3)] public float Top;
[FieldOffset(sizeof(float) * 0)] public Vector2 BottomLeft;
[FieldOffset(sizeof(float) * 2)] public Vector2 TopRight;
public readonly Vector2 BottomRight
{
@@ -42,18 +47,6 @@ namespace Robust.Shared.Maths
get => new(Left, Top);
}
public readonly Vector2 TopRight
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => new(Right, Top);
}
public readonly Vector2 BottomLeft
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => new(Left, Bottom);
}
public readonly float Width
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -89,12 +82,18 @@ namespace Robust.Shared.Maths
/// </summary>
public static readonly Box2 UnitCentered = new(-0.5f, -0.5f, 0.5f, 0.5f);
public Box2(Vector2 bottomLeft, Vector2 topRight) : this(bottomLeft.X, bottomLeft.Y, topRight.X, topRight.Y)
public Box2(Vector2 bottomLeft, Vector2 topRight)
{
Unsafe.SkipInit(out this);
BottomLeft = bottomLeft;
TopRight = topRight;
}
public Box2(float left, float bottom, float right, float top)
{
Unsafe.SkipInit(out this);
Left = left;
Right = right;
Top = top;

View File

@@ -1,29 +1,39 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Robust.Shared.Maths
{
[Serializable]
[StructLayout(LayoutKind.Explicit)]
public struct Box2i : IEquatable<Box2i>
{
public int Left;
public int Right;
public int Top;
public int Bottom;
[FieldOffset(sizeof(int) * 0)] public int Left;
[FieldOffset(sizeof(int) * 1)] public int Bottom;
[FieldOffset(sizeof(int) * 2)] public int Right;
[FieldOffset(sizeof(int) * 3)] public int Top;
[FieldOffset(sizeof(int) * 0)] public Vector2i BottomLeft;
[FieldOffset(sizeof(int) * 2)] public Vector2i TopRight;
public readonly Vector2i BottomRight => new(Right, Bottom);
public readonly Vector2i TopLeft => new(Left, Top);
public readonly Vector2i TopRight => new(Right, Top);
public readonly Vector2i BottomLeft => new(Left, Bottom);
public readonly int Width => Math.Abs(Right - Left);
public readonly int Height => Math.Abs(Top - Bottom);
public readonly Vector2i Size => new(Width, Height);
public Box2i(Vector2i bottomLeft, Vector2i topRight) : this(bottomLeft.X, bottomLeft.Y, topRight.X, topRight.Y)
public Box2i(Vector2i bottomLeft, Vector2i topRight)
{
Unsafe.SkipInit(out this);
BottomLeft = bottomLeft;
TopRight = topRight;
}
public Box2i(int left, int bottom, int right, int top)
{
Unsafe.SkipInit(out this);
Left = left;
Right = right;
Top = top;

View File

@@ -1,4 +1,6 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Robust.Shared.Maths
{
@@ -7,30 +9,32 @@ namespace Robust.Shared.Maths
/// Uses a left-handed coordinate system. This means that X+ is to the right and Y+ down.
/// </summary>
[Serializable]
[StructLayout(LayoutKind.Explicit)]
public struct UIBox2 : IEquatable<UIBox2>
{
/// <summary>
/// The X coordinate of the left edge of the box.
/// </summary>
public float Left;
/// <summary>
/// The X coordinate of the right edge of the box.
/// </summary>
public float Right;
[FieldOffset(sizeof(float) * 0)] public float Left;
/// <summary>
/// The Y coordinate of the top edge of the box.
/// </summary>
public float Top;
[FieldOffset(sizeof(float) * 1)] public float Top;
/// <summary>
/// The X coordinate of the right edge of the box.
/// </summary>
[FieldOffset(sizeof(float) * 2)] public float Right;
/// <summary>
/// The Y coordinate of the bottom of the box.
/// </summary>
public float Bottom;
[FieldOffset(sizeof(float) * 3)] public float Bottom;
[FieldOffset(sizeof(float) * 0)] public Vector2 TopLeft;
[FieldOffset(sizeof(float) * 2)] public Vector2 BottomRight;
public readonly Vector2 BottomRight => new(Right, Bottom);
public readonly Vector2 TopLeft => new(Left, Top);
public readonly Vector2 TopRight => new(Right, Top);
public readonly Vector2 BottomLeft => new(Left, Bottom);
public readonly float Width => MathF.Abs(Right - Left);
@@ -38,12 +42,18 @@ namespace Robust.Shared.Maths
public readonly Vector2 Size => new(Width, Height);
public readonly Vector2 Center => TopLeft + Size / 2;
public UIBox2(Vector2 leftTop, Vector2 rightBottom) : this(leftTop.X, leftTop.Y, rightBottom.X, rightBottom.Y)
public UIBox2(Vector2 leftTop, Vector2 rightBottom)
{
Unsafe.SkipInit(out this);
TopLeft = leftTop;
BottomRight = rightBottom;
}
public UIBox2(float left, float top, float right, float bottom)
{
Unsafe.SkipInit(out this);
Left = left;
Right = right;
Top = top;

View File

@@ -1,29 +1,39 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Robust.Shared.Maths
{
[Serializable]
[StructLayout(LayoutKind.Explicit)]
public struct UIBox2i : IEquatable<UIBox2i>
{
public int Left;
public int Right;
public int Top;
public int Bottom;
[FieldOffset(sizeof(int) * 0)] public int Left;
[FieldOffset(sizeof(int) * 1)] public int Top;
[FieldOffset(sizeof(int) * 2)] public int Right;
[FieldOffset(sizeof(int) * 3)] public int Bottom;
[FieldOffset(sizeof(int) * 0)] public Vector2i TopLeft;
[FieldOffset(sizeof(int) * 2)] public Vector2i BottomRight;
public readonly Vector2i BottomRight => new(Right, Bottom);
public readonly Vector2i TopLeft => new(Left, Top);
public readonly Vector2i TopRight => new(Right, Top);
public readonly Vector2i BottomLeft => new(Left, Bottom);
public readonly int Width => Math.Abs(Right - Left);
public readonly int Height => Math.Abs(Top - Bottom);
public readonly Vector2i Size => new(Width, Height);
public UIBox2i(Vector2i topLeft, Vector2i bottomRight) : this(topLeft.X, topLeft.Y, bottomRight.X, bottomRight.Y)
public UIBox2i(Vector2i topLeft, Vector2i bottomRight)
{
Unsafe.SkipInit(out this);
TopLeft = topLeft;
BottomRight = bottomRight;
}
public UIBox2i(int left, int top, int right, int bottom)
{
Unsafe.SkipInit(out this);
Left = left;
Right = right;
Top = top;
@@ -76,6 +86,7 @@ namespace Robust.Shared.Maths
{
return null;
}
return new UIBox2i(
Vector2i.ComponentMax(TopLeft, other.TopLeft),
Vector2i.ComponentMin(BottomRight, other.BottomRight));