Add FirstNonEmptyBounds method for IDecorationBounds interface.
This provides a more efficient way of determining the bounds by avoiding LINQ. A helper that works directly on arrays prevents allocation of an enumerator when the collection is know to be an array.
This commit is contained in:
@@ -110,6 +110,34 @@ namespace OpenRA.Traits
|
||||
// HACK: This provides a shim for legacy code until it can be rewritten
|
||||
public interface IDecorationBounds { Rectangle DecorationBounds(Actor self, WorldRenderer wr); }
|
||||
public interface IDecorationBoundsInfo : ITraitInfoInterface { }
|
||||
public static class DecorationBoundsExtensions
|
||||
{
|
||||
public static Rectangle FirstNonEmptyBounds(this IEnumerable<IDecorationBounds> decorationBounds, Actor self, WorldRenderer wr)
|
||||
{
|
||||
// PERF: Avoid LINQ.
|
||||
foreach (var decoration in decorationBounds)
|
||||
{
|
||||
var bounds = decoration.DecorationBounds(self, wr);
|
||||
if (!bounds.IsEmpty)
|
||||
return bounds;
|
||||
}
|
||||
|
||||
return Rectangle.Empty;
|
||||
}
|
||||
|
||||
public static Rectangle FirstNonEmptyBounds(this IDecorationBounds[] decorationBounds, Actor self, WorldRenderer wr)
|
||||
{
|
||||
// PERF: Avoid LINQ.
|
||||
foreach (var decoration in decorationBounds)
|
||||
{
|
||||
var bounds = decoration.DecorationBounds(self, wr);
|
||||
if (!bounds.IsEmpty)
|
||||
return bounds;
|
||||
}
|
||||
|
||||
return Rectangle.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public interface IIssueOrder
|
||||
{
|
||||
|
||||
@@ -163,10 +163,7 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
{
|
||||
if (unit.CanBeViewedByPlayer(manager.Self.Owner))
|
||||
{
|
||||
var bounds = unit.TraitsImplementing<IDecorationBounds>()
|
||||
.Select(b => b.DecorationBounds(unit, wr))
|
||||
.FirstOrDefault(b => !b.IsEmpty);
|
||||
|
||||
var bounds = unit.TraitsImplementing<IDecorationBounds>().FirstNonEmptyBounds(unit, wr);
|
||||
yield return new SelectionBoxRenderable(unit, bounds, Color.Red);
|
||||
}
|
||||
}
|
||||
@@ -281,10 +278,7 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
{
|
||||
if (unit.CanBeViewedByPlayer(manager.Self.Owner))
|
||||
{
|
||||
var bounds = unit.TraitsImplementing<IDecorationBounds>()
|
||||
.Select(b => b.DecorationBounds(unit, wr))
|
||||
.FirstOrDefault(b => !b.IsEmpty);
|
||||
|
||||
var bounds = unit.TraitsImplementing<IDecorationBounds>().FirstNonEmptyBounds(unit, wr);
|
||||
yield return new SelectionBoxRenderable(unit, bounds, Color.Red);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
|
||||
public IEnumerable<IRenderable> Render(Actor self, WorldRenderer wr)
|
||||
{
|
||||
var bounds = decorationBounds.Select(b => b.DecorationBounds(self, wr)).FirstOrDefault(b => !b.IsEmpty);
|
||||
var bounds = decorationBounds.FirstNonEmptyBounds(self, wr);
|
||||
var spaceBuffer = (int)(10 / wr.Viewport.Zoom);
|
||||
var effectPos = wr.ProjectedPosition(new int2((bounds.Left + bounds.Right) / 2, bounds.Y - spaceBuffer));
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
var selected = self.World.Selection.Contains(self);
|
||||
var regularWorld = self.World.Type == WorldType.Regular;
|
||||
var statusBars = Game.Settings.Game.StatusBars;
|
||||
var bounds = decorationBounds.Select(b => b.DecorationBounds(self, wr)).FirstOrDefault(b => !b.IsEmpty);
|
||||
var bounds = decorationBounds.FirstNonEmptyBounds(self, wr);
|
||||
|
||||
// Health bars are shown when:
|
||||
// * actor is selected
|
||||
|
||||
@@ -106,7 +106,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
if (!ShouldRender(self) || self.World.FogObscures(self))
|
||||
return Enumerable.Empty<IRenderable>();
|
||||
|
||||
var bounds = decorationBounds.Select(b => b.DecorationBounds(self, wr)).FirstOrDefault(b => !b.IsEmpty);
|
||||
var bounds = decorationBounds.FirstNonEmptyBounds(self, wr);
|
||||
var halfSize = (0.5f * Anim.Image.Size.XY).ToInt2();
|
||||
|
||||
var boundsOffset = new int2(bounds.Left + bounds.Right, bounds.Top + bounds.Bottom) / 2;
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
|
||||
pipImages.PlayFetchIndex(Info.GroupSequence, () => (int)group);
|
||||
|
||||
var bounds = decorationBounds.Select(b => b.DecorationBounds(self, wr)).FirstOrDefault(b => !b.IsEmpty);
|
||||
var bounds = decorationBounds.FirstNonEmptyBounds(self, wr);
|
||||
var boundsOffset = 0.5f * new float2(bounds.Left + bounds.Right, bounds.Top + bounds.Bottom);
|
||||
if (Info.ReferencePoint.HasFlag(ReferencePoints.Top))
|
||||
boundsOffset -= new float2(0, 0.5f * bounds.Height);
|
||||
|
||||
@@ -87,7 +87,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
if (group == null)
|
||||
yield break;
|
||||
|
||||
var bounds = decorationBounds.Select(b => b.DecorationBounds(self, wr)).FirstOrDefault(b => !b.IsEmpty);
|
||||
var bounds = decorationBounds.FirstNonEmptyBounds(self, wr);
|
||||
var number = group.Value.ToString();
|
||||
var halfSize = font.Measure(number) / 2;
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
if (!ShouldRender(self) || self.World.FogObscures(self))
|
||||
return Enumerable.Empty<IRenderable>();
|
||||
|
||||
var bounds = decorationBounds.Select(b => b.DecorationBounds(self, wr)).FirstOrDefault(b => !b.IsEmpty);
|
||||
var bounds = decorationBounds.FirstNonEmptyBounds(self, wr);
|
||||
var halfSize = font.Measure(Info.Text) / 2;
|
||||
|
||||
var boundsOffset = new int2(bounds.Left + bounds.Right, bounds.Top + bounds.Bottom) / 2;
|
||||
|
||||
@@ -138,9 +138,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
var xy = wr.Viewport.ViewToWorld(Viewport.LastMousePos);
|
||||
foreach (var unit in power.UnitsInRange(xy))
|
||||
{
|
||||
var bounds = unit.TraitsImplementing<IDecorationBounds>()
|
||||
.Select(b => b.DecorationBounds(unit, wr))
|
||||
.FirstOrDefault(b => !b.IsEmpty);
|
||||
var bounds = unit.TraitsImplementing<IDecorationBounds>().FirstNonEmptyBounds(unit, wr);
|
||||
yield return new SelectionBoxRenderable(unit, bounds, Color.Red);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,10 +51,7 @@ namespace OpenRA.Mods.Common.Widgets
|
||||
// TODO: Integrate this with SelectionDecorations to unhardcode the *Renderable
|
||||
if (unit.Info.HasTraitInfo<SelectableInfo>())
|
||||
{
|
||||
var bounds = unit.TraitsImplementing<IDecorationBounds>()
|
||||
.Select(b => b.DecorationBounds(unit, worldRenderer))
|
||||
.FirstOrDefault(b => !b.IsEmpty);
|
||||
|
||||
var bounds = unit.TraitsImplementing<IDecorationBounds>().FirstNonEmptyBounds(unit, worldRenderer);
|
||||
new SelectionBarsRenderable(unit, bounds, true, true).Render(worldRenderer);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user