diff --git a/OpenRA.FileFormats/OpenRA.FileFormats.csproj b/OpenRA.FileFormats/OpenRA.FileFormats.csproj index 06edc766a2..4b712ccb84 100644 --- a/OpenRA.FileFormats/OpenRA.FileFormats.csproj +++ b/OpenRA.FileFormats/OpenRA.FileFormats.csproj @@ -114,6 +114,7 @@ + - \ No newline at end of file + diff --git a/OpenRA.FileFormats/Primitives/Cached.cs b/OpenRA.FileFormats/Primitives/Cached.cs new file mode 100644 index 0000000000..8823626eda --- /dev/null +++ b/OpenRA.FileFormats/Primitives/Cached.cs @@ -0,0 +1,60 @@ +#region Copyright & License Information +/* + * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation. For more information, + * see COPYING. + */ +#endregion + +using System; + +namespace OpenRA.FileFormats +{ + public class Cached + { + Func p; + T value; + bool hasValue; + + public Cached(Func p) + { + if (p == null) + throw new ArgumentNullException(); + + this.p = p; + } + + public T Value + { + get + { + if (hasValue) + return value; + + value = p(); + hasValue = true; + return value; + } + } + + public void Force() + { + #pragma warning disable 0168 + var ignored = Value; + #pragma warning restore 0168 + } + + public void Invalidate() + { + hasValue = false; + } + } + + public static class Cached + { + public static Cached New(Func p) { return new Cached(p); } + } +} + diff --git a/OpenRA.Game/Actor.cs b/OpenRA.Game/Actor.cs index 39e2a9055e..890f0d158a 100755 --- a/OpenRA.Game/Actor.cs +++ b/OpenRA.Game/Actor.cs @@ -28,6 +28,8 @@ namespace OpenRA IOccupySpace OccupiesSpace; IHasLocation HasLocation; Lazy Move; + public Cached Bounds; + public Cached ExtendedBounds; public int2 Location { get { @@ -84,10 +86,16 @@ namespace OpenRA ApplyIRender = x => x.Render(this); ApplyRenderModifier = (m, p) => p.ModifyRender(this, m); + + Bounds = Cached.New( () => CalculateBounds(false) ); + ExtendedBounds = Cached.New( () => CalculateBounds(true) ); } public void Tick() { + Bounds.Invalidate(); + ExtendedBounds.Invalidate(); + currentActivity = Util.RunActivity( this, currentActivity ); } @@ -112,7 +120,7 @@ namespace OpenRA // vertically to altitude = 0 to support FindUnitsInCircle queries // When false, the bounding box is given for the actor // at its current altitude - public RectangleF GetBounds(bool useAltitude) + RectangleF CalculateBounds(bool useAltitude) { var size = Size.Value; var loc = CenterLocation - 0.5f * size; diff --git a/OpenRA.Game/Graphics/WorldRenderer.cs b/OpenRA.Game/Graphics/WorldRenderer.cs index 9280b65dd8..f25fde4cea 100644 --- a/OpenRA.Game/Graphics/WorldRenderer.cs +++ b/OpenRA.Game/Graphics/WorldRenderer.cs @@ -125,7 +125,7 @@ namespace OpenRA.Graphics public void DrawSelectionBox(Actor selectedUnit, Color c) { - var bounds = selectedUnit.GetBounds(false); + var bounds = selectedUnit.Bounds.Value; var xy = new float2(bounds.Left, bounds.Top); var Xy = new float2(bounds.Right, bounds.Top); diff --git a/OpenRA.Game/Traits/Selectable.cs b/OpenRA.Game/Traits/Selectable.cs index 4c48e327a9..4c374720cb 100644 --- a/OpenRA.Game/Traits/Selectable.cs +++ b/OpenRA.Game/Traits/Selectable.cs @@ -30,7 +30,7 @@ namespace OpenRA.Traits public void RenderAfterWorld (WorldRenderer wr, Actor self) { - var bounds = self.GetBounds(false); + var bounds = self.Bounds.Value; Color selectionColor = Color.White; var xy = new float2(bounds.Left, bounds.Top); @@ -55,7 +55,7 @@ namespace OpenRA.Traits public void DrawRollover(WorldRenderer wr, Actor self) { - var bounds = self.GetBounds(false); + var bounds = self.Bounds.Value; var xy = new float2(bounds.Left, bounds.Top); var Xy = new float2(bounds.Right, bounds.Top); @@ -184,10 +184,12 @@ namespace OpenRA.Traits var thisRow = pips.GetPips(self); if (thisRow == null) continue; + + var width = self.Bounds.Value.Width; foreach (var pip in thisRow) { - if (pipxyOffset.X+5 > self.GetBounds(false).Width) + if (pipxyOffset.X+5 > width) { pipxyOffset.X = 0; pipxyOffset.Y -= 4; diff --git a/OpenRA.Game/Traits/World/SpatialBins.cs b/OpenRA.Game/Traits/World/SpatialBins.cs index 647499ae92..1d7b6a3f1b 100644 --- a/OpenRA.Game/Traits/World/SpatialBins.cs +++ b/OpenRA.Game/Traits/World/SpatialBins.cs @@ -47,7 +47,7 @@ namespace OpenRA.Traits foreach (var a in self.World.ActorsWithTrait()) { - var bounds = a.Actor.GetBounds(true); + var bounds = a.Actor.ExtendedBounds.Value; if (bounds.Right <= Game.CellSize * self.World.Map.Bounds.Left) continue; if (bounds.Bottom <= Game.CellSize * self.World.Map.Bounds.Top) continue; @@ -81,7 +81,7 @@ namespace OpenRA.Traits return ActorsInBins(a.X / scale, b.X / scale, a.Y / scale, b.Y / scale) .Distinct() - .Where(u => u.IsInWorld && u.GetBounds(true).IntersectsWith(r)); + .Where(u => u.IsInWorld && u.ExtendedBounds.Value.IntersectsWith(r)); } } } diff --git a/OpenRA.Game/WorldUtils.cs b/OpenRA.Game/WorldUtils.cs index 9432f212e4..a8db341db5 100755 --- a/OpenRA.Game/WorldUtils.cs +++ b/OpenRA.Game/WorldUtils.cs @@ -45,7 +45,7 @@ namespace OpenRA var rect = new RectangleF(min.X, min.Y, max.X - min.X, max.Y - min.Y); - var inBox = actors.Where(x => x.GetBounds(true).IntersectsWith(rect)); + var inBox = actors.Where(x => x.ExtendedBounds.Value.IntersectsWith(rect)); return inBox.Where(x => (x.CenterLocation - a).LengthSquared < r * r); } diff --git a/OpenRA.Mods.RA/GainsExperience.cs b/OpenRA.Mods.RA/GainsExperience.cs index 1da8eaa9a5..e8ed897c43 100644 --- a/OpenRA.Mods.RA/GainsExperience.cs +++ b/OpenRA.Mods.RA/GainsExperience.cs @@ -107,8 +107,7 @@ namespace OpenRA.Mods.RA foreach (var r in rs) yield return r; - RankAnim.Tick(); // hack - var bounds = self.GetBounds(false); + var bounds = self.Bounds.Value; yield return new Renderable(RankAnim.Image, new float2(bounds.Right - 6, bounds.Bottom - 8), "effect", self.CenterLocation.Y); }