diff --git a/OpenRA.Mods.Common/EditorBrushes/EditorTilingPathBrush.cs b/OpenRA.Mods.Common/EditorBrushes/EditorTilingPathBrush.cs
index 841d4f92b1..908d6b99f7 100644
--- a/OpenRA.Mods.Common/EditorBrushes/EditorTilingPathBrush.cs
+++ b/OpenRA.Mods.Common/EditorBrushes/EditorTilingPathBrush.cs
@@ -112,10 +112,10 @@ namespace OpenRA.Mods.Common.Widgets
.FirstOrDefault(0);
var isStartDirector =
plan.AutoStart != Direction.None
- && cpos == plan.FirstPoint - Direction.ToCVec(plan.AutoStart);
+ && cpos == plan.FirstPoint - plan.AutoStart.ToCVec();
var isEndDirector =
plan.AutoEnd != Direction.None
- && cpos == plan.LastPoint + Direction.ToCVec(plan.AutoEnd);
+ && cpos == plan.LastPoint + plan.AutoEnd.ToCVec();
return (isInside, isRally, rallyIndex, isStartDirector, isEndDirector);
}
@@ -131,7 +131,7 @@ namespace OpenRA.Mods.Common.Widgets
var offset = plan.FirstPoint - to;
var direction =
offset != CVec.Zero
- ? Direction.FromCVecRounding(offset)
+ ? DirectionExts.ClosestFromCVec(offset)
: Direction.None;
UpdatePlan(plan.WithStart(direction), true);
}
@@ -140,7 +140,7 @@ namespace OpenRA.Mods.Common.Widgets
var offset = to - plan.LastPoint;
var direction =
offset != CVec.Zero
- ? Direction.FromCVecRounding(offset)
+ ? DirectionExts.ClosestFromCVec(offset)
: Direction.None;
UpdatePlan(plan.WithEnd(direction), true);
}
@@ -248,7 +248,7 @@ namespace OpenRA.Mods.Common.Widgets
if (plan.AutoEnd != Direction.None)
yield return new CircleAnnotationRenderable(
- CornerOfCell(plan.LastPoint) + Direction.ToWVec(plan.AutoEnd) * 768,
+ CornerOfCell(plan.LastPoint) + plan.AutoEnd.ToWVec() * 768,
new WDist(256),
2,
plan.End != Direction.None ? Color.Magenta : Color.Gray,
@@ -256,7 +256,7 @@ namespace OpenRA.Mods.Common.Widgets
if (plan.AutoStart != Direction.None)
yield return new CircleAnnotationRenderable(
- CornerOfCell(plan.FirstPoint) - Direction.ToWVec(plan.AutoStart) * 768,
+ CornerOfCell(plan.FirstPoint) - plan.AutoStart.ToWVec() * 768,
new WDist(256),
2,
plan.Start != Direction.None ? Color.Magenta : Color.Gray,
diff --git a/OpenRA.Mods.Common/MapGenerator/Direction.cs b/OpenRA.Mods.Common/MapGenerator/Direction.cs
index 5da45e5975..a3d9203db6 100644
--- a/OpenRA.Mods.Common/MapGenerator/Direction.cs
+++ b/OpenRA.Mods.Common/MapGenerator/Direction.cs
@@ -19,71 +19,80 @@ namespace OpenRA.Mods.Common.MapGenerator
/// Utilities for simple directions and adjacency. Note that coordinate systems might not agree
/// as to which directions are conceptually left/right or up/down.
///
- public static class Direction
+ public enum Direction
{
/// No direction.
- public const int None = -1;
+ None = -1,
/// +X ("right").
- public const int R = 0;
+ R = 0,
/// +X+Y ("right down").
- public const int RD = 1;
+ RD = 1,
/// +Y ("down").
- public const int D = 2;
+ D = 2,
/// -X+Y ("left down").
- public const int LD = 3;
+ LD = 3,
/// -X ("left").
- public const int L = 4;
+ L = 4,
/// -X-Y ("left up").
- public const int LU = 5;
+ LU = 5,
/// -Y ("up").
- public const int U = 6;
+ U = 6,
/// +X-Y ("right up").
- public const int RU = 7;
+ RU = 7,
+ }
+
+ [Flags]
+ public enum DirectionMask
+ {
+ None = 0,
/// Bitmask right.
- public const int MR = 1 << R;
+ MR = 1 << Direction.R,
/// Bitmask right-down.
- public const int MRD = 1 << RD;
+ MRD = 1 << Direction.RD,
/// Bitmask down.
- public const int MD = 1 << D;
+ MD = 1 << Direction.D,
/// Bitmask left-down.
- public const int MLD = 1 << LD;
+ MLD = 1 << Direction.LD,
/// Bitmask left.
- public const int ML = 1 << L;
+ ML = 1 << Direction.L,
/// Bitmask left-up.
- public const int MLU = 1 << LU;
+ MLU = 1 << Direction.LU,
/// Bitmask up.
- public const int MU = 1 << U;
+ MU = 1 << Direction.U,
/// Bitmask right-up.
- public const int MRU = 1 << RU;
+ MRU = 1 << Direction.RU,
+ }
+ public static class DirectionExts
+ {
/// Adjacent offsets with directions, excluding diagonals.
- public static readonly ImmutableArray<(int2, int)> Spread4D =
+ public static readonly ImmutableArray<(int2, Direction)> Spread4D =
[
- (new int2(1, 0), R),
- (new int2(0, 1), D),
- (new int2(-1, 0), L),
- (new int2(0, -1), U)
+ (new int2(1, 0), Direction.R),
+ (new int2(0, 1), Direction.D),
+ (new int2(-1, 0), Direction.L),
+ (new int2(0, -1), Direction.U)
];
/// Adjacent offsets, excluding diagonals.
public static readonly ImmutableArray Spread4 =
- Spread4D.Select(((int2 XY, int _) v) => v.XY).ToImmutableArray();
+ Spread4D.Select(((int2 XY, Direction _) v) => v.XY).ToImmutableArray();
///
/// Adjacent offsets, excluding diagonals. Assumes that CVec(1, 0)
@@ -93,21 +102,21 @@ namespace OpenRA.Mods.Common.MapGenerator
Spread4.Select(xy => new CVec(xy.X, xy.Y)).ToImmutableArray();
/// Adjacent offsets with directions, including diagonals.
- public static readonly ImmutableArray<(int2, int)> Spread8D =
+ public static readonly ImmutableArray<(int2, Direction)> Spread8D =
[
- (new int2(1, 0), R),
- (new int2(1, 1), RD),
- (new int2(0, 1), D),
- (new int2(-1, 1), LD),
- (new int2(-1, 0), L),
- (new int2(-1, -1), LU),
- (new int2(0, -1), U),
- (new int2(1, -1), RU)
+ (new int2(1, 0), Direction.R),
+ (new int2(1, 1), Direction.RD),
+ (new int2(0, 1), Direction.D),
+ (new int2(-1, 1), Direction.LD),
+ (new int2(-1, 0), Direction.L),
+ (new int2(-1, -1), Direction.LU),
+ (new int2(0, -1), Direction.U),
+ (new int2(1, -1), Direction.RU)
];
/// Adjacent offsets, including diagonals.
public static readonly ImmutableArray Spread8 =
- Spread8D.Select(((int2 XY, int _) v) => v.XY).ToImmutableArray();
+ Spread8D.Select(((int2 XY, Direction _) v) => v.XY).ToImmutableArray();
///
/// Adjacent offsets, including diagonals. Assumes that CVec(1, 0)
@@ -117,34 +126,22 @@ namespace OpenRA.Mods.Common.MapGenerator
Spread8.Select(xy => new CVec(xy.X, xy.Y)).ToImmutableArray();
/// Convert a non-none direction to an int2 offset.
- public static int2 ToInt2(int d)
+ public static int2 ToInt2(this Direction direction)
{
- if (d >= 0 && d < 8)
- return Spread8[d];
+ if (direction >= Direction.R && direction <= Direction.RU)
+ return Spread8[(int)direction];
else
throw new ArgumentException("bad direction");
}
- static readonly ImmutableArray KiloVectors =
- [
- new(1024, 0),
- new(724, 724),
- new(0, 1024),
- new(-724, 724),
- new(-1024, 0),
- new(-724, -724),
- new(0, -1024),
- new(724, -724),
- ];
-
///
/// Convert a non-none direction to a CVec offset. Assumes that
/// CVec(1, 0) corresponds to Direction.R.
///
- public static CVec ToCVec(int d)
+ public static CVec ToCVec(this Direction direction)
{
- if (d >= 0 && d < 8)
- return Spread8CVec[d];
+ if (direction >= Direction.R && direction <= Direction.RU)
+ return Spread8CVec[(int)direction];
else
throw new ArgumentException("bad direction");
}
@@ -153,10 +150,10 @@ namespace OpenRA.Mods.Common.MapGenerator
/// Convert a non-none direction to a WVec offset. Assumes that
/// WVec(1, 0, 0) corresponds to Direction.R.
///
- public static WVec ToWVec(int d)
+ public static WVec ToWVec(this Direction direction)
{
- if (d >= 0 && d < 8)
- return new WVec(Spread8[d].X, Spread8[d].Y, 0);
+ if (direction >= Direction.R && direction <= Direction.RU)
+ return new WVec(Spread8[(int)direction].X, Spread8[(int)direction].Y, 0);
else
throw new ArgumentException("bad direction");
}
@@ -166,32 +163,32 @@ namespace OpenRA.Mods.Common.MapGenerator
/// The direction is based purely on the signs of the inputs.
/// Supplying a zero-offset will throw.
///
- public static int FromOffset(int dx, int dy)
+ public static Direction FromOffset(int dx, int dy)
{
if (dx > 0)
{
if (dy > 0)
- return RD;
+ return Direction.RD;
else if (dy < 0)
- return RU;
+ return Direction.RU;
else
- return R;
+ return Direction.R;
}
else if (dx < 0)
{
if (dy > 0)
- return LD;
+ return Direction.LD;
else if (dy < 0)
- return LU;
+ return Direction.LU;
else
- return L;
+ return Direction.L;
}
else
{
if (dy > 0)
- return D;
+ return Direction.D;
else if (dy < 0)
- return U;
+ return Direction.U;
else
throw new ArgumentException("Bad direction");
}
@@ -202,32 +199,37 @@ namespace OpenRA.Mods.Common.MapGenerator
/// The direction with the closest angle wins. Keep inputs to 1000000 or less.
/// Supplying a zero-offset will throw.
///
- public static int FromOffsetRounding(int dx, int dy)
+ public static Direction ClosestFrom(int dx, int dy)
{
if (dx == 0 && dy == 0)
- throw new ArgumentException("Bad direction");
+ throw new ArgumentException("bad direction");
- var d = new int2(dx, dy);
- var direction = None;
- var best = 0;
- for (var i = 0; i < KiloVectors.Length; i++)
+ var absX = Math.Abs(dx);
+ var absY = Math.Abs(dy);
+ var min = Math.Min(absX, absY);
+ var max = Math.Max(absX, absY);
+
+ // 408 / 985 is an approximation of tan(Pi / 8 radians), or tan(22.5 degrees)
+ if (408 * max < 985 * min)
{
- var score = int2.Dot(d, KiloVectors[i]);
- if (score > best)
- {
- best = score;
- direction = i;
- }
+ // Diagonal
+ return FromOffset(dx, dy);
+ }
+ else
+ {
+ // Cardinal
+ if (absX > absY)
+ return FromOffsetNonDiagonal(dx, 0);
+ else
+ return FromOffsetNonDiagonal(0, dy);
}
-
- return direction;
}
///
/// Convert an offset (of arbitrary non-zero magnitude) to a direction.
/// Supplying a zero-offset will throw.
///
- public static int FromInt2(int2 delta)
+ public static Direction FromInt2(int2 delta)
=> FromOffset(delta.X, delta.Y);
///
@@ -235,7 +237,7 @@ namespace OpenRA.Mods.Common.MapGenerator
/// Supplying a zero-offset will throw. Assumes that CVec(1, 0)
/// corresponds to Direction.R.
///
- public static int FromCVec(CVec delta)
+ public static Direction FromCVec(CVec delta)
=> FromOffset(delta.X, delta.Y);
///
@@ -243,23 +245,23 @@ namespace OpenRA.Mods.Common.MapGenerator
/// Supplying a zero-offset will throw. Assumes that CVec(1, 0)
/// corresponds to Direction.R.
///
- public static int FromCVecRounding(CVec delta)
- => FromOffsetRounding(delta.X, delta.Y);
+ public static Direction ClosestFromCVec(CVec delta)
+ => ClosestFrom(delta.X, delta.Y);
///
/// Convert an offset (of arbitrary non-zero magnitude) to a non-diagonal direction.
/// Supplying a zero-offset will throw.
///
- public static int FromOffsetNonDiagonal(int dx, int dy)
+ public static Direction FromOffsetNonDiagonal(int dx, int dy)
{
if (dx - dy > 0 && dx + dy >= 0)
- return R;
+ return Direction.R;
if (dy + dx > 0 && dy - dx >= 0)
- return D;
+ return Direction.D;
if (-dx + dy > 0 && -dx - dy >= 0)
- return L;
+ return Direction.L;
if (-dy - dx > 0 && -dy + dx >= 0)
- return U;
+ return Direction.U;
throw new ArgumentException("bad direction");
}
@@ -267,7 +269,7 @@ namespace OpenRA.Mods.Common.MapGenerator
/// Convert an offset (of arbitrary non-zero magnitude) to a
/// non-diagonal direction. Supplying a zero-offset will throw.
///
- public static int FromInt2NonDiagonal(int2 delta)
+ public static Direction FromInt2NonDiagonal(int2 delta)
=> FromOffsetNonDiagonal(delta.X, delta.Y);
///
@@ -275,81 +277,53 @@ namespace OpenRA.Mods.Common.MapGenerator
/// non-diagonal direction. Supplying a zero-offset will throw. Assumes
/// that CVec(1, 0) corresponds to Direction.R.
///
- public static int FromCVecNonDiagonal(CVec delta)
+ public static Direction FromCVecNonDiagonal(CVec delta)
=> FromOffsetNonDiagonal(delta.X, delta.Y);
/// Return the opposite direction.
- public static int Reverse(int direction)
+ public static Direction Reverse(this Direction direction)
{
- if (direction == None)
- return None;
- return direction ^ 4;
+ if (direction != Direction.None)
+ return (Direction)((int)direction ^ 4);
+ else
+ return Direction.None;
}
- /// Convert a direction to a short string, like "None", "R", "RD", etc.
- public static string ToString(int direction)
+ /// Converts the direction to a mask value.
+ public static DirectionMask ToMask(this Direction direction)
{
- switch (direction)
- {
- case None: return "None";
- case R: return "R";
- case RD: return "RD";
- case D: return "D";
- case LD: return "LD";
- case L: return "L";
- case LU: return "LU";
- case U: return "U";
- case RU: return "RU";
- default: throw new ArgumentException("bad direction");
- }
+ if (direction >= Direction.R && direction <= Direction.RU)
+ return (DirectionMask)(1 << (int)direction);
+ else
+ return DirectionMask.None;
+ }
+ }
+
+ public static class DirectionMaskExts
+ {
+ /// Count the number of set bits (directions) in a direction mask.
+ public static int Count(this DirectionMask mask)
+ {
+ return int.PopCount((int)mask);
}
- /// Count the number of set bits in a direction mask.
- public static int Count(int dm)
+ /// Finds the only direction set in a direction mask or returns None.
+ public static Direction ToDirection(this DirectionMask mask)
{
- var count = 0;
- for (var m = dm; m != 0; m >>= 1)
- if ((m & 1) == 1)
- count++;
-
- return count;
- }
-
- /// Finds the only direction set in a direction mask or returns NONE.
- public static int FromMask(int mask)
- {
- switch (mask)
- {
- case MR: return R;
- case MRD: return RD;
- case MD: return D;
- case MLD: return LD;
- case ML: return L;
- case MLU: return LU;
- case MU: return U;
- case MRU: return RU;
- default: return None;
- }
+ var d = int.Log2((int)mask);
+ if (1 << d == (int)mask)
+ return (Direction)d;
+ else
+ return Direction.None;
}
/// True if diagonal, false if horizontal/vertical, throws otherwise.
- public static bool IsDiagonal(int direction)
+ public static bool IsDiagonal(this Direction direction)
{
- switch (direction)
- {
- case R:
- case D:
- case L:
- case U:
- return false;
- case RD:
- case LD:
- case LU:
- case RU:
- return true;
- default:
- throw new ArgumentException("NONE or bad direction");
- }
+ if (direction >= Direction.R && direction <= Direction.RU)
+ return ((int)direction & 1) == 1;
+ else
+ throw new ArgumentException("None or bad direction");
}
}
}
diff --git a/OpenRA.Mods.Common/MapGenerator/MatrixUtils.cs b/OpenRA.Mods.Common/MapGenerator/MatrixUtils.cs
index 14e87e99f2..e7fb300daa 100644
--- a/OpenRA.Mods.Common/MapGenerator/MatrixUtils.cs
+++ b/OpenRA.Mods.Common/MapGenerator/MatrixUtils.cs
@@ -189,7 +189,7 @@ namespace OpenRA.Mods.Common.MapGenerator
output[xy] = distance;
unprocessed[i] = int.MaxValue;
- foreach (var (offset, direction) in Direction.Spread8D)
+ foreach (var (offset, direction) in DirectionExts.Spread8D)
{
var nextXY = xy + offset;
if (!passable.ContainsXY(nextXY))
@@ -199,7 +199,7 @@ namespace OpenRA.Mods.Common.MapGenerator
if (output[nextXY] != int.MaxValue)
continue;
int nextDistance;
- if (Direction.IsDiagonal(direction))
+ if (direction.IsDiagonal())
nextDistance = distance + Diagonal;
else
nextDistance = distance + Straight;
@@ -250,7 +250,7 @@ namespace OpenRA.Mods.Common.MapGenerator
}
}
- FloodFill(space.Size, [(new int2(x, y), holeCount)], Filler, Direction.Spread4);
+ FloodFill(space.Size, [(new int2(x, y), holeCount)], Filler, DirectionExts.Spread4);
}
const int UNASSIGNED = int.MaxValue;
@@ -322,7 +322,7 @@ namespace OpenRA.Mods.Common.MapGenerator
}
}
- FloodFill(size, seeds, Filler, Direction.Spread4);
+ FloodFill(size, seeds, Filler, DirectionExts.Spread4);
}
var deflatedSize = size + new int2(1, 1);
@@ -346,10 +346,10 @@ namespace OpenRA.Mods.Common.MapGenerator
}
deflated[cx, cy] = (byte)(
- (neighborhood[0] != neighborhood[1] ? Direction.MU : 0) |
- (neighborhood[1] != neighborhood[3] ? Direction.MR : 0) |
- (neighborhood[3] != neighborhood[2] ? Direction.MD : 0) |
- (neighborhood[2] != neighborhood[0] ? Direction.ML : 0));
+ (neighborhood[0] != neighborhood[1] ? DirectionMask.MU : 0) |
+ (neighborhood[1] != neighborhood[3] ? DirectionMask.MR : 0) |
+ (neighborhood[3] != neighborhood[2] ? DirectionMask.MD : 0) |
+ (neighborhood[2] != neighborhood[0] ? DirectionMask.ML : 0));
}
return deflated;
@@ -776,7 +776,7 @@ namespace OpenRA.Mods.Common.MapGenerator
roominess.Size,
seeds,
Filler,
- Direction.Spread8);
+ DirectionExts.Spread8);
return roominess;
}
@@ -813,7 +813,7 @@ namespace OpenRA.Mods.Common.MapGenerator
{
var from = pointArray[i - 1];
var to = pointArray[i];
- var direction = Direction.FromInt2(to - from);
+ var direction = DirectionExts.FromInt2(to - from);
var fx = from.X;
var fy = from.Y;
switch (direction)
@@ -850,7 +850,7 @@ namespace OpenRA.Mods.Common.MapGenerator
return prop;
}
- FloodFill(size, seeds, FillChirality, Direction.Spread4);
+ FloodFill(size, seeds, FillChirality, DirectionExts.Spread4);
return chirality;
}
@@ -898,7 +898,7 @@ namespace OpenRA.Mods.Common.MapGenerator
// Looping paths contain the start/end point twice.
var paths = new List();
- void TracePath(int sx, int sy, int direction)
+ void TracePath(int sx, int sy, Direction direction)
{
var points = new List();
var x = sx;
@@ -1214,18 +1214,18 @@ namespace OpenRA.Mods.Common.MapGenerator
for (var cx = 0; cx < matrix.Size.X; cx++)
{
var fromPos = new int2(cx, cy);
- var fromDm = matrix[fromPos];
- foreach (var (offset, d) in Direction.Spread8D)
+ var fromDm = (DirectionMask)matrix[fromPos];
+ foreach (var (offset, d) in DirectionExts.Spread8D)
{
- if ((fromDm & (1 << d)) == 0)
+ if ((fromDm & d.ToMask()) == DirectionMask.None)
continue;
- var dr = Direction.Reverse(d);
+ var dr = d.Reverse();
var toPos = new int2(cx + offset.X, cy + offset.Y);
- if (matrix.ContainsXY(toPos) && (matrix[toPos] & (1 << dr)) != 0)
+ if (matrix.ContainsXY(toPos) && ((DirectionMask)matrix[toPos] & dr.ToMask()) != DirectionMask.None)
continue;
- matrix[fromPos] = (byte)(output[fromPos] & ~(1 << d));
+ matrix[fromPos] = (byte)((DirectionMask)output[fromPos] & ~d.ToMask());
}
}
}
@@ -1236,17 +1236,17 @@ namespace OpenRA.Mods.Common.MapGenerator
for (var cy = 0; cy < input.Size.Y; cy++)
for (var cx = 0; cx < input.Size.X; cx++)
{
- var dm = input[cx, cy];
- if (Direction.Count(dm) > 2)
+ var dm = (DirectionMask)input[cx, cy];
+ if (dm.Count() > 2)
{
output[cx, cy] = 0;
- foreach (var (offset, d) in Direction.Spread8D)
+ foreach (var (offset, d) in DirectionExts.Spread8D)
{
var xy = new int2(cx + offset.X, cy + offset.Y);
if (!input.ContainsXY(xy))
continue;
- var dr = Direction.Reverse(d);
- output[xy] = (byte)(output[xy] & ~(1 << dr));
+ var dr = d.Reverse();
+ output[xy] = (byte)((DirectionMask)output[xy] & ~dr.ToMask());
}
}
}
@@ -1266,20 +1266,20 @@ namespace OpenRA.Mods.Common.MapGenerator
// Find non-loops, starting at terminals.
var pointArrays = new List();
- void TracePoints(int2 xy, int reverseDm)
+ void TracePoints(int2 xy, DirectionMask reverseDm)
{
var points = new List();
bool AddPoint()
{
points.Add(xy);
- var dm = links[xy] & ~reverseDm;
+ var dm = (DirectionMask)links[xy] & ~reverseDm;
links[xy] = 0;
- foreach (var (offset, d) in Direction.Spread8D)
- if ((dm & (1 << d)) != 0)
+ foreach (var (offset, d) in DirectionExts.Spread8D)
+ if ((dm & d.ToMask()) != DirectionMask.None)
{
xy += offset;
- reverseDm = 1 << Direction.Reverse(d);
+ reverseDm = d.Reverse().ToMask();
return true;
}
@@ -1294,7 +1294,7 @@ namespace OpenRA.Mods.Common.MapGenerator
for (var sy = 0; sy < links.Size.Y; sy++)
for (var sx = 0; sx < links.Size.X; sx++)
- if (Direction.FromMask(links[sx, sy]) != Direction.None)
+ if (((DirectionMask)links[sx, sy]).ToDirection() != Direction.None)
TracePoints(new int2(sx, sy), 0);
// All non-loops have been removed, leaving only loops left.
@@ -1303,7 +1303,7 @@ namespace OpenRA.Mods.Common.MapGenerator
if (links[sx, sy] != 0)
{
// Choose direction with most-significant bit
- var reverseDm = links[sx, sy] & (links[sx, sy] - 1);
+ var reverseDm = (DirectionMask)(links[sx, sy] & (links[sx, sy] - 1));
TracePoints(new int2(sx, sy), reverseDm);
}
@@ -1351,8 +1351,8 @@ namespace OpenRA.Mods.Common.MapGenerator
{
toDelete.Add(point);
if (pointArray.Length < minimumJunctionSeparation)
- foreach (var (offset, d) in Direction.Spread8D)
- if ((links[point] & (1 << d)) != 0)
+ foreach (var (offset, d) in DirectionExts.Spread8D)
+ if (((DirectionMask)links[point] & d.ToMask()) != DirectionMask.None)
toDelete.Add(point + offset);
}
diff --git a/OpenRA.Mods.Common/MapGenerator/PlayableSpace.cs b/OpenRA.Mods.Common/MapGenerator/PlayableSpace.cs
index 383cf219b6..0f31fd1391 100644
--- a/OpenRA.Mods.Common/MapGenerator/PlayableSpace.cs
+++ b/OpenRA.Mods.Common/MapGenerator/PlayableSpace.cs
@@ -123,7 +123,7 @@ namespace OpenRA.Mods.Common.MapGenerator
playable,
[(start, true)],
Filler,
- Direction.Spread4CVec);
+ DirectionExts.Spread4CVec);
}
foreach (var mpos in map.AllCells.MapCoords)
diff --git a/OpenRA.Mods.Common/MapGenerator/TilingPath.cs b/OpenRA.Mods.Common/MapGenerator/TilingPath.cs
index 6ac1315353..2e03c05cec 100644
--- a/OpenRA.Mods.Common/MapGenerator/TilingPath.cs
+++ b/OpenRA.Mods.Common/MapGenerator/TilingPath.cs
@@ -31,7 +31,7 @@ namespace OpenRA.Mods.Common.MapGenerator
/// Direction to use for this terminal.
/// If the direction here is null, it will be determined automatically later.
///
- public int? Direction;
+ public Direction? Direction;
///
/// A string which can match the format used by MultiBrushSegment's Start or End.
@@ -42,11 +42,11 @@ namespace OpenRA.Mods.Common.MapGenerator
{
var direction =
Direction ?? throw new InvalidOperationException("Direction is null");
- return $"{Type}.{MapGenerator.Direction.ToString(direction)}";
+ return $"{Type}.{direction}";
}
}
- public Terminal(string type, int? direction)
+ public Terminal(string type, Direction? direction)
{
Type = type;
Direction = direction;
@@ -249,9 +249,9 @@ namespace OpenRA.Mods.Common.MapGenerator
public readonly CVec Offset;
public readonly CVec Moves;
public readonly CVec[] RelativePoints;
- public readonly int[] Directions;
- public readonly int[] DirectionMasks;
- public readonly int[] ReverseDirectionMasks;
+ public readonly Direction[] Directions;
+ public readonly DirectionMask[] DirectionMasks;
+ public readonly DirectionMask[] ReverseDirectionMasks;
public TilingSegment(MultiBrush multiBrush, int startId, int endId)
{
@@ -264,9 +264,9 @@ namespace OpenRA.Mods.Common.MapGenerator
.Select(p => p - multiBrush.Segment.Points[0])
.ToArray();
- Directions = new int[RelativePoints.Length];
- DirectionMasks = new int[RelativePoints.Length];
- ReverseDirectionMasks = new int[RelativePoints.Length];
+ Directions = new Direction[RelativePoints.Length];
+ DirectionMasks = new DirectionMask[RelativePoints.Length];
+ ReverseDirectionMasks = new DirectionMask[RelativePoints.Length];
// Last point has no direction.
Directions[^1] = Direction.None;
@@ -274,12 +274,12 @@ namespace OpenRA.Mods.Common.MapGenerator
ReverseDirectionMasks[^1] = 0;
for (var i = 0; i < RelativePoints.Length - 1; i++)
{
- var direction = Direction.FromCVec(RelativePoints[i + 1] - RelativePoints[i]);
+ var direction = DirectionExts.FromCVec(RelativePoints[i + 1] - RelativePoints[i]);
if (direction == Direction.None)
throw new ArgumentException("MultiBrushSegment has duplicate points in sequence");
Directions[i] = direction;
- DirectionMasks[i] = 1 << direction;
- ReverseDirectionMasks[i] = 1 << Direction.Reverse(direction);
+ DirectionMasks[i] = direction.ToMask();
+ ReverseDirectionMasks[i] = direction.Reverse().ToMask();
}
}
}
@@ -349,8 +349,8 @@ namespace OpenRA.Mods.Common.MapGenerator
var start = Start;
var end = End;
- start.Direction ??= Direction.FromCVec(Points[1] - Points[0]);
- end.Direction ??= Direction.FromCVec(IsLoop ? Points[1] - Points[0] : Points[^1] - Points[^2]);
+ start.Direction ??= DirectionExts.FromCVec(Points[1] - Points[0]);
+ end.Direction ??= DirectionExts.FromCVec(IsLoop ? Points[1] - Points[0] : Points[^1] - Points[^2]);
var maxSkip = MaxSkip > 0 ? MaxSkip : (2 * MaxDeviation + 1);
@@ -472,7 +472,7 @@ namespace OpenRA.Mods.Common.MapGenerator
lows.Clear();
highs.Clear();
- foreach (var offset in Direction.Spread8)
+ foreach (var offset in DirectionExts.Spread8)
{
var neighbor = xy + offset;
if (!deviations.ContainsXY(neighbor) ||
@@ -502,7 +502,7 @@ namespace OpenRA.Mods.Common.MapGenerator
size,
progressSeeds,
ProgressFiller,
- Direction.Spread8);
+ DirectionExts.Spread8);
var separationSeeds = new List<(int2, int)>();
@@ -521,7 +521,7 @@ namespace OpenRA.Mods.Common.MapGenerator
if (MinSeparation > 0)
{
- foreach (var offset in Direction.Spread8)
+ foreach (var offset in DirectionExts.Spread8)
{
var neighbor = xy + offset;
if (!deviations.ContainsXY(neighbor) ||
@@ -553,7 +553,7 @@ namespace OpenRA.Mods.Common.MapGenerator
size,
separationSeeds,
SeparationFiller,
- Direction.Spread8);
+ DirectionExts.Spread8);
}
var pathStart = points[0];
@@ -861,7 +861,7 @@ namespace OpenRA.Mods.Common.MapGenerator
fallbackDistances.Size,
[(new int2(maxEndDeviation, maxEndDeviation), 0)],
FallbacksFiller,
- Direction.Spread4);
+ DirectionExts.Spread4);
var bestDistance = fallbackDistances.Data.Min();
if (bestDistance == Unreached || bestDistance == Unsolved)
@@ -943,17 +943,17 @@ namespace OpenRA.Mods.Common.MapGenerator
if (inertialRange > points.Length - 1)
inertialRange = points.Length - 1;
- var sd = Direction.FromCVecNonDiagonal(points[inertialRange] - points[0]);
- var ed = Direction.FromCVecNonDiagonal(points[^1] - points[^(inertialRange + 1)]);
+ var sd = DirectionExts.FromCVecNonDiagonal(points[inertialRange] - points[0]);
+ var ed = DirectionExts.FromCVecNonDiagonal(points[^1] - points[^(inertialRange + 1)]);
var newPoints = new CPos[points.Length + extensionLength * 2];
for (var i = 0; i < extensionLength; i++)
- newPoints[i] = points[0] - Direction.ToCVec(sd) * (extensionLength - i);
+ newPoints[i] = points[0] - sd.ToCVec() * (extensionLength - i);
Array.Copy(points, 0, newPoints, extensionLength, points.Length);
for (var i = 0; i < extensionLength; i++)
- newPoints[extensionLength + points.Length + i] = points[^1] + Direction.ToCVec(ed) * (i + 1);
+ newPoints[extensionLength + points.Length + i] = points[^1] + ed.ToCVec() * (i + 1);
return newPoints;
}
@@ -1341,7 +1341,7 @@ namespace OpenRA.Mods.Common.MapGenerator
for (var i = 1; i < points.Length; i++)
{
var offset = lastPoint - points[i];
- if (Direction.ToCVec(Direction.FromCVecNonDiagonal(offset)) != offset)
+ if (DirectionExts.FromCVecNonDiagonal(offset).ToCVec() != offset)
return false;
lastPoint = points[i];
diff --git a/OpenRA.Mods.Common/Traits/World/ExperimentalMapGenerator.cs b/OpenRA.Mods.Common/Traits/World/ExperimentalMapGenerator.cs
index 7a9d7550f9..325f6d7c83 100644
--- a/OpenRA.Mods.Common/Traits/World/ExperimentalMapGenerator.cs
+++ b/OpenRA.Mods.Common/Traits/World/ExperimentalMapGenerator.cs
@@ -1049,7 +1049,7 @@ namespace OpenRA.Mods.Common.Traits
regionMask,
map.AllCells.Where(cpos => regionMask[cpos] == largest.Id).Select(cpos => (cpos, true)),
AdoptPartiallyPlayableIntoLargest,
- Direction.Spread4CVec);
+ DirectionExts.Spread4CVec);
if (param.DenyWalledAreas)
{
@@ -1086,7 +1086,7 @@ namespace OpenRA.Mods.Common.Traits
map.Tiles,
unplayableWater.Select(cpos => (cpos, false)),
ClearWaterBody,
- Direction.Spread4CVec);
+ DirectionExts.Spread4CVec);
}
var replaceable = IdentifyReplaceableTiles(map, replaceabilityMap, actorPlans);
diff --git a/OpenRA.Mods.Common/Traits/World/TilingPathTool.cs b/OpenRA.Mods.Common/Traits/World/TilingPathTool.cs
index 2d589e2f36..7f587ada51 100644
--- a/OpenRA.Mods.Common/Traits/World/TilingPathTool.cs
+++ b/OpenRA.Mods.Common/Traits/World/TilingPathTool.cs
@@ -54,11 +54,11 @@ namespace OpenRA.Mods.Common.Traits
///
public sealed class PathPlan
{
- public readonly int Start;
- public readonly int End;
+ public readonly Direction Start;
+ public readonly Direction End;
public readonly bool Loop;
public readonly ImmutableArray Rallies;
- public int AutoStart
+ public Direction AutoStart
{
get
{
@@ -69,14 +69,14 @@ namespace OpenRA.Mods.Common.Traits
else
{
if (Rallies.Length >= 2)
- return Direction.FromCVecRounding(Rallies[1] - Rallies[0]);
+ return DirectionExts.ClosestFromCVec(Rallies[1] - Rallies[0]);
else
return Direction.None;
}
}
}
- public int AutoEnd
+ public Direction AutoEnd
{
get
{
@@ -91,7 +91,7 @@ namespace OpenRA.Mods.Common.Traits
else
{
if (Rallies.Length >= 2)
- return Direction.FromCVecRounding(Rallies[^1] - Rallies[^2]);
+ return DirectionExts.ClosestFromCVec(Rallies[^1] - Rallies[^2]);
else
return Direction.None;
}
@@ -101,7 +101,7 @@ namespace OpenRA.Mods.Common.Traits
public CPos FirstPoint => Rallies[0];
public CPos LastPoint => Loop ? Rallies[0] : Rallies[^1];
- PathPlan(int start, int end, bool loop, ImmutableArray rallies)
+ PathPlan(Direction start, Direction end, bool loop, ImmutableArray rallies)
{
if (rallies == null || rallies.Length == 0)
throw new ArgumentException("rallies must have at least one point");
@@ -122,13 +122,13 @@ namespace OpenRA.Mods.Common.Traits
}
/// Return a copy, modifying the start direction.
- public PathPlan WithStart(int start)
+ public PathPlan WithStart(Direction start)
{
return new PathPlan(start, End, Loop, Rallies);
}
/// Return a copy, modifying the end direction.
- public PathPlan WithEnd(int end)
+ public PathPlan WithEnd(Direction end)
{
return new PathPlan(Start, end, Loop, Rallies);
}
@@ -191,16 +191,16 @@ namespace OpenRA.Mods.Common.Traits
}
return new PathPlan(
- Direction.Reverse(reversedStart),
- Direction.Reverse(reversedEnd),
+ reversedStart.Reverse(),
+ reversedEnd.Reverse(),
Loop,
Rallies.Skip(1).Append(Rallies[0]).Reverse().ToImmutableArray());
}
else
{
return new PathPlan(
- Direction.Reverse(End),
- Direction.Reverse(Start),
+ End.Reverse(),
+ Start.Reverse(),
Loop,
Rallies.Reverse().ToImmutableArray());
}
@@ -228,7 +228,7 @@ namespace OpenRA.Mods.Common.Traits
var points = new List<(CPos CPos, int RallyIndex)>();
var cpos = Rallies[0];
points.Add((cpos, 0));
- var inertia = Direction.ToCVec(AutoStart);
+ var inertia = AutoStart.ToCVec();
if (inertia.X != 0 && inertia.Y != 0)
inertia = new CVec(inertia.X, 0);
@@ -267,9 +267,9 @@ namespace OpenRA.Mods.Common.Traits
inertia = new CVec(0, yStep);
else
inertia =
- Direction.ToCVec(
- Direction.FromCVecNonDiagonal(
- inertia + new CVec(xStep * 2, yStep * 2)));
+ DirectionExts.FromCVecNonDiagonal(
+ inertia + new CVec(xStep * 2, yStep * 2))
+ .ToCVec();
while (cpos != target)
{