|
|
|
public struct Tile
|
|
|
|
{
|
|
|
|
public Corners<short> Height;
|
|
|
|
|
|
|
|
// TODO: Replace with enum or something more permanent?
|
|
|
|
public byte TexturePrimary;
|
|
|
|
public byte TextureSecondary;
|
|
|
|
public byte TextureBlend;
|
|
|
|
|
|
|
|
public readonly bool IsDefault
|
|
|
|
=> Height == default
|
|
|
|
&& TexturePrimary == 0
|
|
|
|
&& TextureSecondary == 0
|
|
|
|
&& TextureBlend == 0;
|
|
|
|
|
|
|
|
public readonly override string ToString()
|
|
|
|
=> $"Tile {{ Height = {Height}, TexturePrimary = {TexturePrimary}, TextureSecondary = {TextureSecondary}, TextureBlend = {TextureBlend} }}";
|
|
|
|
}
|
|
|
|
|
|
|
|
public readonly record struct TilePos(int X, int Z)
|
|
|
|
{
|
|
|
|
public Vector2 Center => new(X + 0.5f, Z + 0.5f);
|
|
|
|
|
|
|
|
public static TilePos operator +(TilePos left, Vector2I right) => new(left.X + right.X, left.Z + right.Y);
|
|
|
|
public static TilePos operator +(TilePos left, (int X, int Y) right) => new(left.X + right.X, left.Z + right.Y);
|
|
|
|
|
|
|
|
public static TilePos operator -(TilePos left, Vector2I right) => new(left.X - right.X, left.Z - right.Y);
|
|
|
|
public static TilePos operator -(TilePos left, (int X, int Y) right) => new(left.X - right.X, left.Z - right.Y);
|
|
|
|
|
|
|
|
public static explicit operator TilePos(Vector2I value) => new(value.X, value.Y);
|
|
|
|
public static explicit operator TilePos(Vector2 value) => new(FloorToInt(value.X), FloorToInt(value.Y));
|
|
|
|
public static explicit operator Vector2I(TilePos pos) => new(pos.X, pos.Z);
|
|
|
|
}
|
|
|
|
|
|
|
|
public struct Corners<T>(T topLeft, T topRight, T bottomRight, T bottomLeft)
|
|
|
|
: IEquatable<Corners<T>>
|
|
|
|
where T : IEquatable<T>
|
|
|
|
{
|
|
|
|
public T TopLeft = topLeft;
|
|
|
|
public T TopRight = topRight;
|
|
|
|
public T BottomRight = bottomRight;
|
|
|
|
public T BottomLeft = bottomLeft;
|
|
|
|
|
|
|
|
public Corners(T value)
|
|
|
|
: this(value, value, value, value) { }
|
|
|
|
|
|
|
|
public T this[Corner corner] {
|
|
|
|
readonly get => corner switch {
|
|
|
|
Corner.TopLeft => TopLeft,
|
|
|
|
Corner.TopRight => TopRight,
|
|
|
|
Corner.BottomRight => BottomRight,
|
|
|
|
Corner.BottomLeft => BottomLeft,
|
|
|
|
_ => throw new ArgumentException($"Invalid Corner value '{corner}'", nameof(corner)),
|
|
|
|
};
|
|
|
|
set { switch (corner) {
|
|
|
|
case Corner.TopLeft : TopLeft = value; break;
|
|
|
|
case Corner.TopRight : TopRight = value; break;
|
|
|
|
case Corner.BottomRight : BottomRight = value; break;
|
|
|
|
case Corner.BottomLeft : BottomLeft = value; break;
|
|
|
|
default: throw new ArgumentException($"Invalid Corner value '{corner}'", nameof(corner));
|
|
|
|
} }
|
|
|
|
}
|
|
|
|
|
|
|
|
public readonly bool Equals(Corners<T> other)
|
|
|
|
=> TopLeft .Equals(other.TopLeft )
|
|
|
|
&& TopRight .Equals(other.TopRight )
|
|
|
|
&& BottomRight.Equals(other.BottomRight)
|
|
|
|
&& BottomLeft .Equals(other.BottomLeft );
|
|
|
|
|
|
|
|
public readonly override bool Equals(object obj)
|
|
|
|
=> (obj is Corners<T> other) && Equals(other);
|
|
|
|
public readonly override int GetHashCode()
|
|
|
|
=> HashCode.Combine(TopLeft, TopRight, BottomRight, BottomLeft);
|
|
|
|
|
|
|
|
public readonly override string ToString()
|
|
|
|
=> $"Corners(TopLeft: {TopLeft}, TopRight: {TopRight}, BottomRight: {BottomRight}, BottomLeft: {BottomLeft})";
|
|
|
|
|
|
|
|
public static bool operator ==(Corners<T> left, Corners<T> right) => left.Equals(right);
|
|
|
|
public static bool operator !=(Corners<T> left, Corners<T> right) => !left.Equals(right);
|
|
|
|
}
|