Shroud, combine IsVisible and IsExplored into a single function.
This commit is contained in:
@@ -81,6 +81,19 @@ namespace OpenRA.Mods.Common.Traits
|
||||
All = Top | Right | Bottom | Left
|
||||
}
|
||||
|
||||
// Index into neighbors array.
|
||||
enum Neighbor
|
||||
{
|
||||
Top = 0,
|
||||
Right,
|
||||
Bottom,
|
||||
Left,
|
||||
TopLeft,
|
||||
TopRight,
|
||||
BottomRight,
|
||||
BottomLeft
|
||||
}
|
||||
|
||||
readonly struct TileInfo
|
||||
{
|
||||
public readonly float3 ScreenPosition;
|
||||
@@ -96,17 +109,20 @@ namespace OpenRA.Mods.Common.Traits
|
||||
readonly ShroudRendererInfo info;
|
||||
readonly World world;
|
||||
readonly Map map;
|
||||
readonly Edges notVisibleEdges;
|
||||
readonly (Edges, Edges) notVisibleEdgesPair;
|
||||
readonly byte variantStride;
|
||||
readonly byte[] edgesToSpriteIndexOffset;
|
||||
|
||||
// PERF: Allocate once.
|
||||
readonly Shroud.CellVisibility[] neighbors = new Shroud.CellVisibility[8];
|
||||
|
||||
readonly CellLayer<TileInfo> tileInfos;
|
||||
readonly CellLayer<bool> cellsDirty;
|
||||
bool anyCellDirty;
|
||||
readonly (Sprite Sprite, float Scale, float Alpha)[] fogSprites, shroudSprites;
|
||||
|
||||
Shroud shroud;
|
||||
Func<PPos, bool> visibleUnderShroud, visibleUnderFog;
|
||||
Func<PPos, Shroud.CellVisibility> cellVisibility;
|
||||
TerrainSpriteLayer shroudLayer, fogLayer;
|
||||
PaletteReference shroudPaletteReference, fogPaletteReference;
|
||||
bool disposed;
|
||||
@@ -161,16 +177,26 @@ namespace OpenRA.Mods.Common.Traits
|
||||
}
|
||||
}
|
||||
|
||||
int spriteCount;
|
||||
if (info.UseExtendedIndex)
|
||||
{
|
||||
notVisibleEdgesPair = (Edges.AllSides, Edges.AllSides);
|
||||
spriteCount = (int)Edges.All;
|
||||
}
|
||||
else
|
||||
{
|
||||
notVisibleEdgesPair = (Edges.AllCorners, Edges.AllCorners);
|
||||
spriteCount = (int)Edges.AllCorners;
|
||||
}
|
||||
|
||||
// Mapping of shrouded directions -> sprite index
|
||||
edgesToSpriteIndexOffset = new byte[(byte)(info.UseExtendedIndex ? Edges.All : Edges.AllCorners) + 1];
|
||||
edgesToSpriteIndexOffset = new byte[spriteCount + 1];
|
||||
for (var i = 0; i < info.Index.Length; i++)
|
||||
edgesToSpriteIndexOffset[info.Index[i]] = (byte)i;
|
||||
|
||||
if (info.OverrideFullShroud != null)
|
||||
edgesToSpriteIndexOffset[info.OverrideShroudIndex] = (byte)(variantStride - 1);
|
||||
|
||||
notVisibleEdges = info.UseExtendedIndex ? Edges.AllSides : Edges.AllCorners;
|
||||
|
||||
world.RenderPlayerChanged += WorldOnRenderPlayerChanged;
|
||||
}
|
||||
|
||||
@@ -188,11 +214,9 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
// All tiles are visible in the editor
|
||||
if (w.Type == WorldType.Editor)
|
||||
visibleUnderShroud = _ => true;
|
||||
cellVisibility = puv => Shroud.CellVisibility.Visible;
|
||||
else
|
||||
visibleUnderShroud = puv => map.Contains(puv);
|
||||
|
||||
visibleUnderFog = puv => map.Contains(puv);
|
||||
cellVisibility = puv => (map.Contains(puv) ? Shroud.CellVisibility.Visible | Shroud.CellVisibility.Explored : Shroud.CellVisibility.Hidden);
|
||||
|
||||
var shroudBlend = shroudSprites[0].Sprite.BlendMode;
|
||||
if (shroudSprites.Any(s => s.Sprite.BlendMode != shroudBlend))
|
||||
@@ -211,33 +235,61 @@ namespace OpenRA.Mods.Common.Traits
|
||||
WorldOnRenderPlayerChanged(world.RenderPlayer);
|
||||
}
|
||||
|
||||
Edges GetEdges(PPos puv, Func<PPos, bool> isVisible)
|
||||
Shroud.CellVisibility[] GetNeighborsVisbility(PPos puv)
|
||||
{
|
||||
if (!isVisible(puv))
|
||||
return notVisibleEdges;
|
||||
|
||||
var cell = ((MPos)puv).ToCPos(map);
|
||||
neighbors[(int)Neighbor.Top] = cellVisibility((PPos)(cell + new CVec(0, -1)).ToMPos(map));
|
||||
neighbors[(int)Neighbor.Right] = cellVisibility((PPos)(cell + new CVec(1, 0)).ToMPos(map));
|
||||
neighbors[(int)Neighbor.Bottom] = cellVisibility((PPos)(cell + new CVec(0, 1)).ToMPos(map));
|
||||
neighbors[(int)Neighbor.Left] = cellVisibility((PPos)(cell + new CVec(-1, 0)).ToMPos(map));
|
||||
|
||||
neighbors[(int)Neighbor.TopLeft] = cellVisibility((PPos)(cell + new CVec(-1, -1)).ToMPos(map));
|
||||
neighbors[(int)Neighbor.TopRight] = cellVisibility((PPos)(cell + new CVec(1, -1)).ToMPos(map));
|
||||
neighbors[(int)Neighbor.BottomRight] = cellVisibility((PPos)(cell + new CVec(1, 1)).ToMPos(map));
|
||||
neighbors[(int)Neighbor.BottomLeft] = cellVisibility((PPos)(cell + new CVec(-1, 1)).ToMPos(map));
|
||||
|
||||
return neighbors;
|
||||
}
|
||||
|
||||
Edges GetEdges(Shroud.CellVisibility[] neighbors, Shroud.CellVisibility visibleMask)
|
||||
{
|
||||
// If a side is shrouded then we also count the corners.
|
||||
var edge = Edges.None;
|
||||
if (!isVisible((PPos)(cell + new CVec(0, -1)).ToMPos(map))) edge |= Edges.Top;
|
||||
if (!isVisible((PPos)(cell + new CVec(1, 0)).ToMPos(map))) edge |= Edges.Right;
|
||||
if (!isVisible((PPos)(cell + new CVec(0, 1)).ToMPos(map))) edge |= Edges.Bottom;
|
||||
if (!isVisible((PPos)(cell + new CVec(-1, 0)).ToMPos(map))) edge |= Edges.Left;
|
||||
var edges = Edges.None;
|
||||
if ((neighbors[(int)Neighbor.Top] & visibleMask) == 0) edges |= Edges.Top;
|
||||
if ((neighbors[(int)Neighbor.Right] & visibleMask) == 0) edges |= Edges.Right;
|
||||
if ((neighbors[(int)Neighbor.Bottom] & visibleMask) == 0) edges |= Edges.Bottom;
|
||||
if ((neighbors[(int)Neighbor.Left] & visibleMask) == 0) edges |= Edges.Left;
|
||||
|
||||
var ucorner = edge & Edges.AllCorners;
|
||||
if (!isVisible((PPos)(cell + new CVec(-1, -1)).ToMPos(map))) edge |= Edges.TopLeft;
|
||||
if (!isVisible((PPos)(cell + new CVec(1, -1)).ToMPos(map))) edge |= Edges.TopRight;
|
||||
if (!isVisible((PPos)(cell + new CVec(1, 1)).ToMPos(map))) edge |= Edges.BottomRight;
|
||||
if (!isVisible((PPos)(cell + new CVec(-1, 1)).ToMPos(map))) edge |= Edges.BottomLeft;
|
||||
var ucorner = edges & Edges.AllCorners;
|
||||
if ((neighbors[(int)Neighbor.TopLeft] & visibleMask) == 0) edges |= Edges.TopLeft;
|
||||
if ((neighbors[(int)Neighbor.TopRight] & visibleMask) == 0) edges |= Edges.TopRight;
|
||||
if ((neighbors[(int)Neighbor.BottomRight] & visibleMask) == 0) edges |= Edges.BottomRight;
|
||||
if ((neighbors[(int)Neighbor.BottomLeft] & visibleMask) == 0) edges |= Edges.BottomLeft;
|
||||
|
||||
// RA provides a set of frames for tiles with shrouded
|
||||
// corners but unshrouded edges. We want to detect this
|
||||
// situation without breaking the edge -> corner enabling
|
||||
// in other combinations. The XOR turns off the corner
|
||||
// bits that are enabled twice, which gives the behavior
|
||||
// bits that are enabled twice, which gives the sprite offset
|
||||
// we want here.
|
||||
return info.UseExtendedIndex ? edge ^ ucorner : edge & Edges.AllCorners;
|
||||
return info.UseExtendedIndex ? edges ^ ucorner : edges & Edges.AllCorners;
|
||||
}
|
||||
|
||||
(Edges, Edges) GetEdges(PPos puv)
|
||||
{
|
||||
var cv = cellVisibility(puv);
|
||||
|
||||
// If a cell is covered by shroud, then all neigbhors are covered by shroud and fog.
|
||||
if (cv == Shroud.CellVisibility.Hidden)
|
||||
return notVisibleEdgesPair;
|
||||
|
||||
var ncv = GetNeighborsVisbility(puv);
|
||||
|
||||
// If a cell is covered by fog, then all neigbhors are as well.
|
||||
var edgesFog = cv.HasFlag(Shroud.CellVisibility.Visible) ? GetEdges(ncv, Shroud.CellVisibility.Visible) : notVisibleEdgesPair.Item2;
|
||||
|
||||
var edgesShroud = GetEdges(ncv, Shroud.CellVisibility.Explored | Shroud.CellVisibility.Visible);
|
||||
return (edgesShroud, edgesFog);
|
||||
}
|
||||
|
||||
void WorldOnRenderPlayerChanged(Player player)
|
||||
@@ -251,14 +303,13 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
if (newShroud != null)
|
||||
{
|
||||
visibleUnderShroud = puv => newShroud.IsExplored(puv);
|
||||
visibleUnderFog = puv => newShroud.IsVisible(puv);
|
||||
cellVisibility = puv => newShroud.GetVisibility(puv);
|
||||
newShroud.OnShroudChanged += UpdateShroudCell;
|
||||
}
|
||||
else
|
||||
{
|
||||
visibleUnderShroud = puv => map.Contains(puv);
|
||||
visibleUnderFog = puv => map.Contains(puv);
|
||||
// Visible under shroud: Explored. Visible under fog: Visible.
|
||||
cellVisibility = puv => (map.Contains(puv) ? Shroud.CellVisibility.Visible | Shroud.CellVisibility.Explored : Shroud.CellVisibility.Hidden);
|
||||
}
|
||||
|
||||
shroud = newShroud;
|
||||
@@ -287,12 +338,13 @@ namespace OpenRA.Mods.Common.Traits
|
||||
cellsDirty[uv] = false;
|
||||
|
||||
var tileInfo = tileInfos[uv];
|
||||
var shroudSprite = GetSprite(shroudSprites, GetEdges(puv, visibleUnderShroud), tileInfo.Variant);
|
||||
var (edgesShroud, edgesFog) = GetEdges(puv);
|
||||
var shroudSprite = GetSprite(shroudSprites, edgesShroud, tileInfo.Variant);
|
||||
var shroudPos = tileInfo.ScreenPosition;
|
||||
if (shroudSprite.Sprite != null)
|
||||
shroudPos += shroudSprite.Sprite.Offset - 0.5f * shroudSprite.Sprite.Size;
|
||||
|
||||
var fogSprite = GetSprite(fogSprites, GetEdges(puv, visibleUnderFog), tileInfo.Variant);
|
||||
var fogSprite = GetSprite(fogSprites, edgesFog, tileInfo.Variant);
|
||||
var fogPos = tileInfo.ScreenPosition;
|
||||
if (fogSprite.Sprite != null)
|
||||
fogPos += fogSprite.Sprite.Offset - 0.5f * fogSprite.Sprite.Size;
|
||||
|
||||
@@ -22,6 +22,9 @@ namespace OpenRA.Mods.Common.Widgets
|
||||
{
|
||||
public sealed class RadarWidget : Widget, IDisposable
|
||||
{
|
||||
public readonly int ColorFog = Color.FromArgb(128, Color.Black).ToArgb();
|
||||
public readonly int ColorShroud = Color.Black.ToArgb();
|
||||
|
||||
public string WorldInteractionController = null;
|
||||
public int AnimationLength = 5;
|
||||
public string RadarOnlineSound = null;
|
||||
@@ -240,10 +243,11 @@ namespace OpenRA.Mods.Common.Widgets
|
||||
void UpdateShroudCell(PPos puv)
|
||||
{
|
||||
var color = 0;
|
||||
if (!currentPlayer.Shroud.IsExplored(puv))
|
||||
color = Color.Black.ToArgb();
|
||||
else if (!currentPlayer.Shroud.IsVisible(puv))
|
||||
color = Color.FromArgb(128, Color.Black).ToArgb();
|
||||
var cv = currentPlayer.Shroud.GetVisibility(puv);
|
||||
if (cv == Shroud.CellVisibility.Hidden)
|
||||
color = ColorShroud;
|
||||
else if (cv.HasFlag(Shroud.CellVisibility.Visible))
|
||||
color = ColorFog;
|
||||
|
||||
var stride = radarSheet.Size.Width;
|
||||
unsafe
|
||||
|
||||
Reference in New Issue
Block a user