Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid allocations when generating RadarSignatureCells. #14438

Merged
merged 1 commit into from Dec 11, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
19 changes: 6 additions & 13 deletions OpenRA.Mods.Common/Traits/Radar/AppearsOnRadar.cs
Expand Up @@ -30,12 +30,8 @@ public class AppearsOnRadarInfo : ConditionalTraitInfo

public class AppearsOnRadar : ConditionalTrait<AppearsOnRadarInfo>, IRadarSignature
{
static readonly IEnumerable<Pair<CPos, Color>> NoCells = Enumerable.Empty<Pair<CPos, Color>>();
IRadarColorModifier modifier;

Color currentColor = Color.Transparent;
Func<Pair<CPos, SubCell>, Pair<CPos, Color>> cellToSignature;

public AppearsOnRadar(AppearsOnRadarInfo info)
: base(info) { }

Expand All @@ -45,27 +41,24 @@ protected override void Created(Actor self)
modifier = self.TraitsImplementing<IRadarColorModifier>().FirstOrDefault();
}

public IEnumerable<Pair<CPos, Color>> RadarSignatureCells(Actor self)
public void PopulateRadarSignatureCells(Actor self, List<Pair<CPos, Color>> destinationBuffer)
{
var viewer = self.World.RenderPlayer ?? self.World.LocalPlayer;
if (IsTraitDisabled || (viewer != null && !Info.ValidStances.HasStance(self.Owner.Stances[viewer])))
return NoCells;
return;

var color = Game.Settings.Game.UsePlayerStanceColors ? self.Owner.PlayerStanceColor(self) : self.Owner.Color.RGB;
if (modifier != null)
color = modifier.RadarColorOverride(self, color);

if (Info.UseLocation)
return new[] { Pair.New(self.Location, color) };

// PERF: Cache cellToSignature delegate to avoid allocations as color does not change often.
if (currentColor != color)
{
currentColor = color;
cellToSignature = c => Pair.New(c.First, color);
destinationBuffer.Add(Pair.New(self.Location, color));
return;
}

return self.OccupiesSpace.OccupiedCells().Select(cellToSignature);
foreach (var cell in self.OccupiesSpace.OccupiedCells())
destinationBuffer.Add(Pair.New(cell.First, color));
}
}
}
6 changes: 4 additions & 2 deletions OpenRA.Mods.Common/Traits/World/EditorActorLayer.cs
Expand Up @@ -266,9 +266,11 @@ public List<MiniYamlNode> Save()
return nodes;
}

public IEnumerable<Pair<CPos, Color>> RadarSignatureCells(Actor self)
public void PopulateRadarSignatureCells(Actor self, List<Pair<CPos, Color>> destinationBuffer)
{
return cellMap.SelectMany(c => c.Value.Select(p => Pair.New(c.Key, p.Owner.Color.RGB)));
foreach (var previewsForCell in cellMap)
foreach (var preview in previewsForCell.Value)
destinationBuffer.Add(Pair.New(previewsForCell.Key, preview.Owner.Color.RGB));
}
}
}
2 changes: 1 addition & 1 deletion OpenRA.Mods.Common/TraitsInterfaces.cs
Expand Up @@ -354,7 +354,7 @@ public interface IMove

public interface IRadarSignature
{
IEnumerable<Pair<CPos, Color>> RadarSignatureCells(Actor self);
void PopulateRadarSignatureCells(Actor self, List<Pair<CPos, Color>> destinationBuffer);
}

public interface IRadarColorModifier { Color RadarColorOverride(Actor self, Color color); }
Expand Down
7 changes: 6 additions & 1 deletion OpenRA.Mods.Common/Widgets/RadarWidget.cs
Expand Up @@ -15,6 +15,7 @@
using System.Linq;
using OpenRA.Graphics;
using OpenRA.Mods.Common.Traits;
using OpenRA.Primitives;
using OpenRA.Traits;
using OpenRA.Widgets;

Expand Down Expand Up @@ -361,6 +362,8 @@ public override void Tick()
var stride = radarSheet.Size.Width;
Array.Clear(radarData, 4 * actorSprite.Bounds.Top * stride, 4 * actorSprite.Bounds.Height * stride);

var cells = new List<Pair<CPos, Color>>();

unsafe
{
fixed (byte* colorBytes = &radarData[0])
Expand All @@ -372,7 +375,9 @@ public override void Tick()
if (!t.Actor.IsInWorld || world.FogObscures(t.Actor))
continue;

foreach (var cell in t.Trait.RadarSignatureCells(t.Actor))
cells.Clear();
t.Trait.PopulateRadarSignatureCells(t.Actor, cells);
foreach (var cell in cells)
{
if (!world.Map.Contains(cell.First))
continue;
Expand Down