Convert Direction.cs to enums and extensions
- Converts OpenRA.Mods.Common/MapGenerator/Direction.cs over to using Direction and DirectionMask enums - Moves direction-related utilities into Exts classes. - Simplifies some direction utility logic. Only very small numerical precision behavioral changes.
This commit is contained in:
committed by
Gustas Kažukauskas
parent
99253702c5
commit
7538943f59
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
/// </summary>
|
||||
public static class Direction
|
||||
public enum Direction
|
||||
{
|
||||
/// <summary>No direction.</summary>
|
||||
public const int None = -1;
|
||||
None = -1,
|
||||
|
||||
/// <summary>+X ("right").</summary>
|
||||
public const int R = 0;
|
||||
R = 0,
|
||||
|
||||
/// <summary>+X+Y ("right down").</summary>
|
||||
public const int RD = 1;
|
||||
RD = 1,
|
||||
|
||||
/// <summary>+Y ("down").</summary>
|
||||
public const int D = 2;
|
||||
D = 2,
|
||||
|
||||
/// <summary>-X+Y ("left down").</summary>
|
||||
public const int LD = 3;
|
||||
LD = 3,
|
||||
|
||||
/// <summary>-X ("left").</summary>
|
||||
public const int L = 4;
|
||||
L = 4,
|
||||
|
||||
/// <summary>-X-Y ("left up").</summary>
|
||||
public const int LU = 5;
|
||||
LU = 5,
|
||||
|
||||
/// <summary>-Y ("up").</summary>
|
||||
public const int U = 6;
|
||||
U = 6,
|
||||
|
||||
/// <summary>+X-Y ("right up").</summary>
|
||||
public const int RU = 7;
|
||||
RU = 7,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum DirectionMask
|
||||
{
|
||||
None = 0,
|
||||
|
||||
/// <summary>Bitmask right.</summary>
|
||||
public const int MR = 1 << R;
|
||||
MR = 1 << Direction.R,
|
||||
|
||||
/// <summary>Bitmask right-down.</summary>
|
||||
public const int MRD = 1 << RD;
|
||||
MRD = 1 << Direction.RD,
|
||||
|
||||
/// <summary>Bitmask down.</summary>
|
||||
public const int MD = 1 << D;
|
||||
MD = 1 << Direction.D,
|
||||
|
||||
/// <summary>Bitmask left-down.</summary>
|
||||
public const int MLD = 1 << LD;
|
||||
MLD = 1 << Direction.LD,
|
||||
|
||||
/// <summary>Bitmask left.</summary>
|
||||
public const int ML = 1 << L;
|
||||
ML = 1 << Direction.L,
|
||||
|
||||
/// <summary>Bitmask left-up.</summary>
|
||||
public const int MLU = 1 << LU;
|
||||
MLU = 1 << Direction.LU,
|
||||
|
||||
/// <summary>Bitmask up.</summary>
|
||||
public const int MU = 1 << U;
|
||||
MU = 1 << Direction.U,
|
||||
|
||||
/// <summary>Bitmask right-up.</summary>
|
||||
public const int MRU = 1 << RU;
|
||||
MRU = 1 << Direction.RU,
|
||||
}
|
||||
|
||||
public static class DirectionExts
|
||||
{
|
||||
/// <summary>Adjacent offsets with directions, excluding diagonals.</summary>
|
||||
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)
|
||||
];
|
||||
|
||||
/// <summary>Adjacent offsets, excluding diagonals.</summary>
|
||||
public static readonly ImmutableArray<int2> Spread4 =
|
||||
Spread4D.Select(((int2 XY, int _) v) => v.XY).ToImmutableArray();
|
||||
Spread4D.Select(((int2 XY, Direction _) v) => v.XY).ToImmutableArray();
|
||||
|
||||
/// <summary>
|
||||
/// 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();
|
||||
|
||||
/// <summary>Adjacent offsets with directions, including diagonals.</summary>
|
||||
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)
|
||||
];
|
||||
|
||||
/// <summary>Adjacent offsets, including diagonals.</summary>
|
||||
public static readonly ImmutableArray<int2> Spread8 =
|
||||
Spread8D.Select(((int2 XY, int _) v) => v.XY).ToImmutableArray();
|
||||
Spread8D.Select(((int2 XY, Direction _) v) => v.XY).ToImmutableArray();
|
||||
|
||||
/// <summary>
|
||||
/// 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();
|
||||
|
||||
/// <summary>Convert a non-none direction to an int2 offset.</summary>
|
||||
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<int2> 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),
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// Convert a non-none direction to a CVec offset. Assumes that
|
||||
/// CVec(1, 0) corresponds to Direction.R.
|
||||
/// </summary>
|
||||
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.
|
||||
/// </summary>
|
||||
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.
|
||||
/// </summary>
|
||||
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.
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert an offset (of arbitrary non-zero magnitude) to a direction.
|
||||
/// Supplying a zero-offset will throw.
|
||||
/// </summary>
|
||||
public static int FromInt2(int2 delta)
|
||||
public static Direction FromInt2(int2 delta)
|
||||
=> FromOffset(delta.X, delta.Y);
|
||||
|
||||
/// <summary>
|
||||
@@ -235,7 +237,7 @@ namespace OpenRA.Mods.Common.MapGenerator
|
||||
/// Supplying a zero-offset will throw. Assumes that CVec(1, 0)
|
||||
/// corresponds to Direction.R.
|
||||
/// </summary>
|
||||
public static int FromCVec(CVec delta)
|
||||
public static Direction FromCVec(CVec delta)
|
||||
=> FromOffset(delta.X, delta.Y);
|
||||
|
||||
/// <summary>
|
||||
@@ -243,23 +245,23 @@ namespace OpenRA.Mods.Common.MapGenerator
|
||||
/// Supplying a zero-offset will throw. Assumes that CVec(1, 0)
|
||||
/// corresponds to Direction.R.
|
||||
/// </summary>
|
||||
public static int FromCVecRounding(CVec delta)
|
||||
=> FromOffsetRounding(delta.X, delta.Y);
|
||||
public static Direction ClosestFromCVec(CVec delta)
|
||||
=> ClosestFrom(delta.X, delta.Y);
|
||||
|
||||
/// <summary>
|
||||
/// Convert an offset (of arbitrary non-zero magnitude) to a non-diagonal direction.
|
||||
/// Supplying a zero-offset will throw.
|
||||
/// </summary>
|
||||
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.
|
||||
/// </summary>
|
||||
public static int FromInt2NonDiagonal(int2 delta)
|
||||
public static Direction FromInt2NonDiagonal(int2 delta)
|
||||
=> FromOffsetNonDiagonal(delta.X, delta.Y);
|
||||
|
||||
/// <summary>
|
||||
@@ -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.
|
||||
/// </summary>
|
||||
public static int FromCVecNonDiagonal(CVec delta)
|
||||
public static Direction FromCVecNonDiagonal(CVec delta)
|
||||
=> FromOffsetNonDiagonal(delta.X, delta.Y);
|
||||
|
||||
/// <summary>Return the opposite direction.</summary>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>Convert a direction to a short string, like "None", "R", "RD", etc.</summary>
|
||||
public static string ToString(int direction)
|
||||
/// <summary>Converts the direction to a mask value.</summary>
|
||||
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
|
||||
{
|
||||
/// <summary>Count the number of set bits (directions) in a direction mask.</summary>
|
||||
public static int Count(this DirectionMask mask)
|
||||
{
|
||||
return int.PopCount((int)mask);
|
||||
}
|
||||
|
||||
/// <summary>Count the number of set bits in a direction mask.</summary>
|
||||
public static int Count(int dm)
|
||||
/// <summary>Finds the only direction set in a direction mask or returns None.</summary>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>Finds the only direction set in a direction mask or returns NONE.</summary>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>True if diagonal, false if horizontal/vertical, throws otherwise.</summary>
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<int2[]>();
|
||||
void TracePath(int sx, int sy, int direction)
|
||||
void TracePath(int sx, int sy, Direction direction)
|
||||
{
|
||||
var points = new List<int2>();
|
||||
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<int2[]>();
|
||||
|
||||
void TracePoints(int2 xy, int reverseDm)
|
||||
void TracePoints(int2 xy, DirectionMask reverseDm)
|
||||
{
|
||||
var points = new List<int2>();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ namespace OpenRA.Mods.Common.MapGenerator
|
||||
playable,
|
||||
[(start, true)],
|
||||
Filler,
|
||||
Direction.Spread4CVec);
|
||||
DirectionExts.Spread4CVec);
|
||||
}
|
||||
|
||||
foreach (var mpos in map.AllCells.MapCoords)
|
||||
|
||||
@@ -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.
|
||||
/// </summary>
|
||||
public int? Direction;
|
||||
public Direction? Direction;
|
||||
|
||||
/// <summary>
|
||||
/// 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];
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -54,11 +54,11 @@ namespace OpenRA.Mods.Common.Traits
|
||||
/// </summary>
|
||||
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<CPos> 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<CPos> rallies)
|
||||
PathPlan(Direction start, Direction end, bool loop, ImmutableArray<CPos> 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
|
||||
}
|
||||
|
||||
/// <summary>Return a copy, modifying the start direction.</summary>
|
||||
public PathPlan WithStart(int start)
|
||||
public PathPlan WithStart(Direction start)
|
||||
{
|
||||
return new PathPlan(start, End, Loop, Rallies);
|
||||
}
|
||||
|
||||
/// <summary>Return a copy, modifying the end direction.</summary>
|
||||
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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user