diff --git a/OpenRA.Game/Map/ProjectedCellLayer.cs b/OpenRA.Game/Map/ProjectedCellLayer.cs index c62df59db0..98dd943532 100644 --- a/OpenRA.Game/Map/ProjectedCellLayer.cs +++ b/OpenRA.Game/Map/ProjectedCellLayer.cs @@ -9,6 +9,7 @@ */ #endregion +using System; using OpenRA.Primitives; namespace OpenRA @@ -53,5 +54,15 @@ namespace OpenRA { return Bounds.Contains(uv.U, uv.V); } + + public int IndexOf(T value, int startIndex) + { + return Array.IndexOf(Entries, value, startIndex); + } + + public void SetAll(T value) + { + Array.Fill(Entries, value); + } } } diff --git a/OpenRA.Game/Traits/Player/Shroud.cs b/OpenRA.Game/Traits/Player/Shroud.cs index c106baa3c2..70ba1e51f5 100644 --- a/OpenRA.Game/Traits/Player/Shroud.cs +++ b/OpenRA.Game/Traits/Player/Shroud.cs @@ -182,48 +182,22 @@ namespace OpenRA.Traits // We loop over the direct index that represents the PPos in // the ProjectedCellLayers, converting to a PPos only if // it is needed (which is the uncommon case.) - var maxIndex = touched.MaxIndex; - for (var index = 0; index < maxIndex; index++) + if (disabledChanged) { - // PERF: Most cells are not touched - if (!touched[index] && !disabledChanged) - continue; - - touched[index] = false; - - var type = ShroudCellType.Shroud; - - if (explored[index]) + touched.SetAll(false); + var maxIndex = touched.MaxIndex; + for (var index = 0; index < maxIndex; index++) + UpdateCell(index, self); + } + else + { + // PERF: Most cells are unchanged, use IndexOf for fast vectorized search. + var index = touched.IndexOf(true, 0); + while (index != -1) { - var count = visibleCount[index]; - if (!shroudGenerationEnabled || count > 0 || generatedShroudCount[index] == 0) - { - if (passiveVisibilityEnabled) - count += passiveVisibleCount[index]; - - type = count > 0 ? ShroudCellType.Visible : ShroudCellType.Fog; - } - } - - // PERF: Most cells are unchanged - var oldResolvedType = resolvedType[index]; - if (type != oldResolvedType || disabledChanged) - { - resolvedType[index] = type; - var puv = touched.PPosFromIndex(index); - if (map.Contains(puv)) - OnShroudChanged(puv); - - if (!disabledChanged && (fogEnabled || !ExploreMapEnabled)) - { - if (type == ShroudCellType.Visible) - RevealedCells++; - else if (fogEnabled && oldResolvedType == ShroudCellType.Visible) - RevealedCells--; - } - - if (self.Owner.WinState == WinState.Lost) - RevealedCells = 0; + touched[index] = false; + UpdateCell(index, self); + index = touched.IndexOf(true, index + 1); } } @@ -231,6 +205,44 @@ namespace OpenRA.Traits disabledChanged = false; } + void UpdateCell(int index, Actor self) + { + var type = ShroudCellType.Shroud; + + if (explored[index]) + { + var count = visibleCount[index]; + if (!shroudGenerationEnabled || count > 0 || generatedShroudCount[index] == 0) + { + if (passiveVisibilityEnabled) + count += passiveVisibleCount[index]; + + type = count > 0 ? ShroudCellType.Visible : ShroudCellType.Fog; + } + } + + // PERF: Most cells are unchanged + var oldResolvedType = resolvedType[index]; + if (type != oldResolvedType || disabledChanged) + { + resolvedType[index] = type; + var puv = touched.PPosFromIndex(index); + if (map.Contains(puv)) + OnShroudChanged(puv); + + if (!disabledChanged && (fogEnabled || !ExploreMapEnabled)) + { + if (type == ShroudCellType.Visible) + RevealedCells++; + else if (fogEnabled && oldResolvedType == ShroudCellType.Visible) + RevealedCells--; + } + + if (self.Owner.WinState == WinState.Lost) + RevealedCells = 0; + } + } + public static IEnumerable ProjectedCellsInRange(Map map, WPos pos, WDist minRange, WDist maxRange, int maxHeightDelta = -1) { // Account for potential extra half-cell from odd-height terrain