You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
139 lines
4.5 KiB
139 lines
4.5 KiB
using Dictionary = Godot.Collections.Dictionary; |
|
|
|
public readonly record struct TilePos(int X, int Y) |
|
{ |
|
public TilePos GetNeighbor(Side side) |
|
=> side switch { |
|
Side.Left => new(X - 1, Y), |
|
Side.Top => new(X, Y - 1), |
|
Side.Right => new(X + 1, Y), |
|
Side.Bottom => new(X, Y + 1), |
|
_ => throw new ArgumentException($"Invalid Side value '{side}'", nameof(side)), |
|
}; |
|
|
|
public TilePos GetNeighbor(Corner corner) |
|
=> corner switch { |
|
Corner.TopLeft => new(X - 1, Y - 1), |
|
Corner.TopRight => new(X + 1, Y - 1), |
|
Corner.BottomRight => new(X + 1, Y + 1), |
|
Corner.BottomLeft => new(X - 1, Y + 1), |
|
_ => throw new ArgumentException($"Invalid Corner value '{corner}'", nameof(corner)), |
|
}; |
|
|
|
public static TilePos From(Vector2I value) => new(value.X, value.Y); |
|
public Vector2I ToVector2I() => new(X, Y); |
|
} |
|
|
|
public struct Tile |
|
{ |
|
public Corners<float> Height; |
|
|
|
// TODO: Replace with enum or something more permanent? |
|
public int TexturePrimary; |
|
public int TextureSecondary; |
|
public int TextureBlend; |
|
|
|
|
|
public static Tile FromDictionary(Dictionary dict) |
|
{ |
|
if (dict == null) return default; |
|
|
|
float topLeft, topRight, bottomRight, bottomLeft; |
|
switch (dict["heights"]) { |
|
case { VariantType: Variant.Type.Float } variant: |
|
var height = (float)variant; |
|
(topLeft, topRight, bottomRight, bottomLeft) = (height, height, height, height); |
|
break; |
|
case { VariantType: Variant.Type.PackedFloat32Array } variant: |
|
var heights = (float[])variant; |
|
(topLeft, topRight, bottomRight, bottomLeft) = (heights[0], heights[1], heights[2], heights[3]); |
|
break; |
|
default: throw new Exception("Invalid variant type"); |
|
}; |
|
|
|
int texturePrimary, textureSecondary, textureBlend; |
|
switch (dict["texture"]) { |
|
case { VariantType: Variant.Type.Int } variant: |
|
var texture = (int)variant; |
|
(texturePrimary, textureSecondary, textureBlend) = (texture, 0, 0); |
|
break; |
|
case { VariantType: Variant.Type.PackedInt32Array } variant: |
|
var textures = (int[])variant; |
|
(texturePrimary, textureSecondary, textureBlend) = (textures[0], textures[1], textures[2]); |
|
break; |
|
default: throw new Exception("Invalid variant type"); |
|
}; |
|
|
|
return new(){ |
|
Height = new(topLeft, topRight, bottomRight, bottomLeft), |
|
TexturePrimary = texturePrimary, |
|
TextureSecondary = textureSecondary, |
|
TextureBlend = textureBlend, |
|
}; |
|
} |
|
|
|
public readonly Dictionary ToDictionary() |
|
{ |
|
if (Height.IsZeroApprox() && (TexturePrimary == 0) && (TextureBlend == 0)) |
|
return null; |
|
return new(){ |
|
["heights"] = Height.IsEqualApprox() ? Height.TopLeft : new[]{ Height.TopLeft, Height.TopRight, Height.BottomRight, Height.BottomLeft }, |
|
["texture"] = (TextureBlend == 0) ? TexturePrimary : new[]{ TexturePrimary, TextureSecondary, TextureBlend }, |
|
}; |
|
} |
|
} |
|
|
|
public struct Corners<T>(T topLeft, T topRight, T bottomRight, T bottomLeft) |
|
{ |
|
public T TopLeft = topLeft; |
|
public T TopRight = topRight; |
|
public T BottomRight = bottomRight; |
|
public T BottomLeft = bottomLeft; |
|
|
|
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 void Deconstruct( |
|
out T topLeft , out T topRight, |
|
out T bottomRight, out T bottomLeft) |
|
{ |
|
topLeft = TopLeft; |
|
topRight = TopRight; |
|
bottomRight = BottomRight; |
|
bottomLeft = BottomLeft; |
|
} |
|
} |
|
|
|
public static class CornersExtensions |
|
{ |
|
public static void Adjust(this ref Corners<float> self, float amount) |
|
{ |
|
self.TopLeft += amount; |
|
self.TopRight += amount; |
|
self.BottomRight += amount; |
|
self.BottomLeft += amount; |
|
} |
|
|
|
public static bool IsZeroApprox(this Corners<float> self) |
|
=> Mathf.IsZeroApprox(self.TopLeft ) && Mathf.IsZeroApprox(self.TopRight ) |
|
&& Mathf.IsZeroApprox(self.BottomRight) && Mathf.IsZeroApprox(self.BottomLeft); |
|
|
|
public static bool IsEqualApprox(this Corners<float> self) |
|
=> Mathf.IsEqualApprox(self.TopLeft, self.TopRight ) |
|
&& Mathf.IsEqualApprox(self.TopLeft, self.BottomRight) |
|
&& Mathf.IsEqualApprox(self.TopLeft, self.BottomLeft ); |
|
}
|
|
|