diff --git a/OpenRA.Game/Exts.cs b/OpenRA.Game/Exts.cs index 5244557755..4d2aea2e72 100644 --- a/OpenRA.Game/Exts.cs +++ b/OpenRA.Game/Exts.cs @@ -151,6 +151,26 @@ namespace OpenRA return xs.ElementAt(r.Next(xs.Count)); } + public static Rectangle Union(this IEnumerable rects) + { + // PERF: Avoid LINQ. + var first = true; + var result = Rectangle.Empty; + foreach (var rect in rects) + { + if (first) + { + first = false; + result = rect; + continue; + } + + result = Rectangle.Union(rect, result); + } + + return result; + } + public static float Product(this IEnumerable xs) { return xs.Aggregate(1f, (a, x) => a * x); diff --git a/OpenRA.Game/Traits/World/ScreenMap.cs b/OpenRA.Game/Traits/World/ScreenMap.cs index 9cc3672fb8..93d6876ebf 100644 --- a/OpenRA.Game/Traits/World/ScreenMap.cs +++ b/OpenRA.Game/Traits/World/ScreenMap.cs @@ -219,31 +219,6 @@ namespace OpenRA.Traits return partitionedRenderableFrozenActors[p].InBox(RectWithCorners(a, b)).Where(frozenActorIsValid); } - Rectangle AggregateBounds(IEnumerable screenBounds) - { - if (!screenBounds.Any()) - return Rectangle.Empty; - - var bounds = screenBounds.First(); - foreach (var b in screenBounds.Skip(1)) - bounds = Rectangle.Union(bounds, b); - - return bounds; - } - - Rectangle AggregateBounds(IEnumerable vertices) - { - if (!vertices.Any()) - return Rectangle.Empty; - - var first = vertices.First(); - var rect = new Rectangle(first.X, first.Y, 0, 0); - foreach (var v in vertices.Skip(1)) - rect = Rectangle.Union(rect, new Rectangle(v.X, v.Y, 0, 0)); - - return rect; - } - public void TickRender() { foreach (var a in addOrUpdateActors) @@ -261,7 +236,7 @@ namespace OpenRA.Traits else partitionedMouseActors.Remove(a); - var screenBounds = AggregateBounds(a.ScreenBounds(worldRenderer)); + var screenBounds = a.ScreenBounds(worldRenderer).Union(); if (!screenBounds.Size.IsEmpty) { if (partitionedRenderableActors.Contains(a)) @@ -298,7 +273,7 @@ namespace OpenRA.Traits else partitionedMouseFrozenActors[kv.Key].Remove(fa); - var screenBounds = AggregateBounds(fa.ScreenBounds); + var screenBounds = fa.ScreenBounds.Union(); if (!screenBounds.Size.IsEmpty) { if (partitionedRenderableFrozenActors[kv.Key].Contains(fa)) diff --git a/OpenRA.Mods.Common/Graphics/DefaultSpriteSequence.cs b/OpenRA.Mods.Common/Graphics/DefaultSpriteSequence.cs index 8a84f87a66..9f3491635e 100644 --- a/OpenRA.Mods.Common/Graphics/DefaultSpriteSequence.cs +++ b/OpenRA.Mods.Common/Graphics/DefaultSpriteSequence.cs @@ -324,12 +324,7 @@ namespace OpenRA.Mods.Common.Graphics if (ShadowStart > 0) boundSprites = boundSprites.Concat(SpriteBounds(sprites, Frames, ShadowStart, Facings, Length, Stride, transpose)); - if (boundSprites.Any()) - { - Bounds = boundSprites.First(); - foreach (var b in boundSprites.Skip(1)) - Bounds = Rectangle.Union(Bounds, b); - } + Bounds = boundSprites.Union(); } catch (FormatException f) { diff --git a/OpenRA.Mods.Common/Traits/World/EditorActorPreview.cs b/OpenRA.Mods.Common/Traits/World/EditorActorPreview.cs index a039452a22..942fdbf2a3 100644 --- a/OpenRA.Mods.Common/Traits/World/EditorActorPreview.cs +++ b/OpenRA.Mods.Common/Traits/World/EditorActorPreview.cs @@ -92,12 +92,7 @@ namespace OpenRA.Mods.Common.Traits // If this is a problem, then we may need to fetch the area from somewhere else var r = previews.SelectMany(p => p.ScreenBounds(worldRenderer, CenterPosition)); - if (r.Any()) - { - Bounds = r.First(); - foreach (var rr in r.Skip(1)) - Bounds = Rectangle.Union(Bounds, rr); - } + Bounds = r.Union(); SelectionBox = new SelectionBoxRenderable(new WPos(CenterPosition.X, CenterPosition.Y, 8192), new Rectangle(Bounds.X, Bounds.Y, Bounds.Width, Bounds.Height), Color.White); diff --git a/OpenRA.Mods.Common/Widgets/ActorPreviewWidget.cs b/OpenRA.Mods.Common/Widgets/ActorPreviewWidget.cs index f7923729a7..154eb8a5aa 100644 --- a/OpenRA.Mods.Common/Widgets/ActorPreviewWidget.cs +++ b/OpenRA.Mods.Common/Widgets/ActorPreviewWidget.cs @@ -53,20 +53,10 @@ namespace OpenRA.Mods.Common.Widgets .ToArray(); // Calculate the preview bounds - PreviewOffset = int2.Zero; - IdealPreviewSize = int2.Zero; - var r = preview.SelectMany(p => p.ScreenBounds(worldRenderer, WPos.Zero)); - - if (r.Any()) - { - var b = r.First(); - foreach (var rr in r.Skip(1)) - b = Rectangle.Union(b, rr); - - IdealPreviewSize = new int2(b.Width, b.Height); - PreviewOffset = -new int2(b.Left, b.Top) - IdealPreviewSize / 2; - } + var b = r.Union(); + IdealPreviewSize = new int2(b.Width, b.Height); + PreviewOffset = -new int2(b.Left, b.Top) - IdealPreviewSize / 2; } IFinalizedRenderable[] renderables; diff --git a/OpenRA.Mods.Common/Widgets/ProductionPaletteWidget.cs b/OpenRA.Mods.Common/Widgets/ProductionPaletteWidget.cs index 7d1031964a..d5e6dcbe58 100644 --- a/OpenRA.Mods.Common/Widgets/ProductionPaletteWidget.cs +++ b/OpenRA.Mods.Common/Widgets/ProductionPaletteWidget.cs @@ -425,7 +425,7 @@ namespace OpenRA.Mods.Common.Widgets DisplayedIconCount++; } - eventBounds = icons.Any() ? icons.Keys.Aggregate(Rectangle.Union) : Rectangle.Empty; + eventBounds = icons.Keys.Union(); if (oldIconCount != DisplayedIconCount) OnIconCountChanged(oldIconCount, DisplayedIconCount); diff --git a/OpenRA.Mods.Common/Widgets/SupportPowersWidget.cs b/OpenRA.Mods.Common/Widgets/SupportPowersWidget.cs index 91a0d36424..a6f1720e94 100644 --- a/OpenRA.Mods.Common/Widgets/SupportPowersWidget.cs +++ b/OpenRA.Mods.Common/Widgets/SupportPowersWidget.cs @@ -154,7 +154,7 @@ namespace OpenRA.Mods.Common.Widgets IconCount++; } - eventBounds = icons.Any() ? icons.Keys.Aggregate(Rectangle.Union) : Rectangle.Empty; + eventBounds = icons.Keys.Union(); if (oldIconCount != IconCount) OnIconCountChanged(oldIconCount, IconCount);