From 04fb0f209d31b1bb46135f0488695e0c50e3f77a Mon Sep 17 00:00:00 2001 From: reaperrr Date: Thu, 28 Sep 2017 11:15:40 +0200 Subject: [PATCH] Spatially partition some actor overlays --- OpenRA.Game/Graphics/WorldRenderer.cs | 19 +++++++++++-------- OpenRA.Game/Traits/TraitsInterfaces.cs | 14 ++++++++++++-- OpenRA.Mods.Cnc/Traits/Minelayer.cs | 2 ++ .../Traits/Render/RenderJammerCircle.cs | 2 ++ .../Traits/Render/RenderShroudCircle.cs | 2 ++ .../Traits/Buildings/BaseProvider.cs | 2 ++ .../Traits/Render/DrawLineToTarget.cs | 2 ++ .../Traits/Render/RenderDebugState.cs | 2 ++ .../Traits/Render/RenderDetectionCircle.cs | 2 ++ .../Traits/Render/RenderRangeCircle.cs | 2 ++ .../Traits/Render/SelectionDecorations.cs | 2 ++ .../Traits/Render/WithDecoration.cs | 3 +++ .../Traits/Render/WithRangeCircle.cs | 2 ++ .../WithSpriteControlGroupDecoration.cs | 2 ++ .../Render/WithTextControlGroupDecoration.cs | 2 ++ .../Traits/Render/WithTextDecoration.cs | 2 ++ 16 files changed, 52 insertions(+), 10 deletions(-) diff --git a/OpenRA.Game/Graphics/WorldRenderer.cs b/OpenRA.Game/Graphics/WorldRenderer.cs index af48f27acd..a5e7715a4b 100644 --- a/OpenRA.Game/Graphics/WorldRenderer.cs +++ b/OpenRA.Game/Graphics/WorldRenderer.cs @@ -100,9 +100,9 @@ namespace OpenRA.Graphics palettes[name].Palette = pal; } - List GenerateRenderables() + List GenerateRenderables(IEnumerable actorsInBox) { - var actors = World.ScreenMap.RenderableActorsInBox(Viewport.TopLeft, Viewport.BottomRight).Append(World.WorldActor); + var actors = actorsInBox.Append(World.WorldActor); if (World.RenderPlayer != null) actors = actors.Append(World.RenderPlayer.PlayerActor); @@ -126,13 +126,15 @@ namespace OpenRA.Graphics return renderables; } - List GenerateOverlayRenderables() + List GenerateOverlayRenderables(IEnumerable actorsInBox) { - var aboveShroud = World.ActorsWithTrait().Where(a => a.Actor.IsInWorld && !a.Actor.Disposed) - .SelectMany(a => a.Trait.RenderAboveShroud(a.Actor, this)); + var aboveShroud = World.ActorsWithTrait() + .Where(a => a.Actor.IsInWorld && !a.Actor.Disposed && (!a.Trait.SpatiallyPartitionable || actorsInBox.Contains(a.Actor))) + .SelectMany(a => a.Trait.RenderAboveShroud(a.Actor, this)); - var aboveShroudSelected = World.Selection.Actors.Where(a => !a.Disposed) + var aboveShroudSelected = World.Selection.Actors.Where(a => a.IsInWorld && !a.Disposed) .SelectMany(a => a.TraitsImplementing() + .Where(t => !t.SpatiallyPartitionable || actorsInBox.Contains(a)) .SelectMany(t => t.RenderAboveShroud(a, this))); var aboveShroudEffects = World.Effects.Select(e => e as IEffectAboveShroud) @@ -169,7 +171,8 @@ namespace OpenRA.Graphics RefreshPalette(); - var renderables = GenerateRenderables(); + var onScreenActors = World.ScreenMap.RenderableActorsInBox(Viewport.TopLeft, Viewport.BottomRight); + var renderables = GenerateRenderables(onScreenActors); var bounds = Viewport.GetScissorBounds(World.Type != WorldType.Editor); Game.Renderer.EnableScissor(bounds); @@ -202,7 +205,7 @@ namespace OpenRA.Graphics Game.Renderer.DisableScissor(); - var finalOverlayRenderables = GenerateOverlayRenderables(); + var finalOverlayRenderables = GenerateOverlayRenderables(onScreenActors); // HACK: Keep old grouping behaviour var groupedOverlayRenderables = finalOverlayRenderables.GroupBy(prs => prs.GetType()); diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index 860d633d8b..80c4c4714a 100644 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -322,8 +322,18 @@ namespace OpenRA.Traits public interface IRenderAboveWorld { void RenderAboveWorld(Actor self, WorldRenderer wr); } public interface IRenderShroud { void RenderShroud(Shroud shroud, WorldRenderer wr); } - public interface IRenderAboveShroud { IEnumerable RenderAboveShroud(Actor self, WorldRenderer wr); } - public interface IRenderAboveShroudWhenSelected { IEnumerable RenderAboveShroud(Actor self, WorldRenderer wr); } + + public interface IRenderAboveShroud + { + IEnumerable RenderAboveShroud(Actor self, WorldRenderer wr); + bool SpatiallyPartitionable { get; } + } + + public interface IRenderAboveShroudWhenSelected + { + IEnumerable RenderAboveShroud(Actor self, WorldRenderer wr); + bool SpatiallyPartitionable { get; } + } public interface ITargetableInfo : ITraitInfoInterface { diff --git a/OpenRA.Mods.Cnc/Traits/Minelayer.cs b/OpenRA.Mods.Cnc/Traits/Minelayer.cs index e3a98b0d77..b46ae758a8 100644 --- a/OpenRA.Mods.Cnc/Traits/Minelayer.cs +++ b/OpenRA.Mods.Cnc/Traits/Minelayer.cs @@ -156,6 +156,8 @@ namespace OpenRA.Mods.Cnc.Traits WVec.Zero, -511, pal, 1f, true); } + bool IRenderAboveShroudWhenSelected.SpatiallyPartitionable { get { return false; } } + class MinefieldOrderGenerator : IOrderGenerator { readonly List minelayers; diff --git a/OpenRA.Mods.Cnc/Traits/Render/RenderJammerCircle.cs b/OpenRA.Mods.Cnc/Traits/Render/RenderJammerCircle.cs index 5e6b2b37b6..e9594b752b 100644 --- a/OpenRA.Mods.Cnc/Traits/Render/RenderJammerCircle.cs +++ b/OpenRA.Mods.Cnc/Traits/Render/RenderJammerCircle.cs @@ -60,5 +60,7 @@ namespace OpenRA.Mods.Cnc.Traits Color.FromArgb(96, Color.Black)); } } + + bool IRenderAboveShroudWhenSelected.SpatiallyPartitionable { get { return false; } } } } \ No newline at end of file diff --git a/OpenRA.Mods.Cnc/Traits/Render/RenderShroudCircle.cs b/OpenRA.Mods.Cnc/Traits/Render/RenderShroudCircle.cs index c3bbd3f688..c692eb7ff4 100644 --- a/OpenRA.Mods.Cnc/Traits/Render/RenderShroudCircle.cs +++ b/OpenRA.Mods.Cnc/Traits/Render/RenderShroudCircle.cs @@ -56,5 +56,7 @@ namespace OpenRA.Mods.Cnc.Traits { return RangeCircleRenderables(self, wr); } + + bool IRenderAboveShroudWhenSelected.SpatiallyPartitionable { get { return false; } } } } \ No newline at end of file diff --git a/OpenRA.Mods.Common/Traits/Buildings/BaseProvider.cs b/OpenRA.Mods.Common/Traits/Buildings/BaseProvider.cs index 0fdecca6a6..b507ce3314 100644 --- a/OpenRA.Mods.Common/Traits/Buildings/BaseProvider.cs +++ b/OpenRA.Mods.Common/Traits/Buildings/BaseProvider.cs @@ -99,6 +99,8 @@ namespace OpenRA.Mods.Common.Traits return RangeCircleRenderables(wr); } + bool IRenderAboveShroudWhenSelected.SpatiallyPartitionable { get { return false; } } + float ISelectionBar.GetValue() { // Visible to player and allies diff --git a/OpenRA.Mods.Common/Traits/Render/DrawLineToTarget.cs b/OpenRA.Mods.Common/Traits/Render/DrawLineToTarget.cs index de31bd024f..848009a499 100644 --- a/OpenRA.Mods.Common/Traits/Render/DrawLineToTarget.cs +++ b/OpenRA.Mods.Common/Traits/Render/DrawLineToTarget.cs @@ -83,6 +83,8 @@ namespace OpenRA.Mods.Common.Traits } } + bool IRenderAboveShroudWhenSelected.SpatiallyPartitionable { get { return false; } } + void INotifyBecomingIdle.OnBecomingIdle(Actor a) { if (a.IsIdle) diff --git a/OpenRA.Mods.Common/Traits/Render/RenderDebugState.cs b/OpenRA.Mods.Common/Traits/Render/RenderDebugState.cs index c442ca7582..a191cb5648 100644 --- a/OpenRA.Mods.Common/Traits/Render/RenderDebugState.cs +++ b/OpenRA.Mods.Common/Traits/Render/RenderDebugState.cs @@ -97,5 +97,7 @@ namespace OpenRA.Mods.Common.Traits.Render var aiSquadInfo = "{0}, {1}".F(squad.Type, squad.TargetActor); yield return new TextRenderable(font, self.CenterPosition + offset, 0, color, aiSquadInfo); } + + bool IRenderAboveShroudWhenSelected.SpatiallyPartitionable { get { return true; } } } } diff --git a/OpenRA.Mods.Common/Traits/Render/RenderDetectionCircle.cs b/OpenRA.Mods.Common/Traits/Render/RenderDetectionCircle.cs index 74b1fedbd3..e25cf71891 100644 --- a/OpenRA.Mods.Common/Traits/Render/RenderDetectionCircle.cs +++ b/OpenRA.Mods.Common/Traits/Render/RenderDetectionCircle.cs @@ -69,6 +69,8 @@ namespace OpenRA.Mods.Common.Traits.Render info.ContrastColor); } + bool IRenderAboveShroudWhenSelected.SpatiallyPartitionable { get { return false; } } + void ITick.Tick(Actor self) { lineAngle += info.UpdateLineTick; diff --git a/OpenRA.Mods.Common/Traits/Render/RenderRangeCircle.cs b/OpenRA.Mods.Common/Traits/Render/RenderRangeCircle.cs index 6a3b7f9367..a5b120f459 100644 --- a/OpenRA.Mods.Common/Traits/Render/RenderRangeCircle.cs +++ b/OpenRA.Mods.Common/Traits/Render/RenderRangeCircle.cs @@ -112,5 +112,7 @@ namespace OpenRA.Mods.Common.Traits.Render { return RangeCircleRenderables(wr); } + + bool IRenderAboveShroudWhenSelected.SpatiallyPartitionable { get { return false; } } } } diff --git a/OpenRA.Mods.Common/Traits/Render/SelectionDecorations.cs b/OpenRA.Mods.Common/Traits/Render/SelectionDecorations.cs index c6598f0c98..9cbdb358a3 100644 --- a/OpenRA.Mods.Common/Traits/Render/SelectionDecorations.cs +++ b/OpenRA.Mods.Common/Traits/Render/SelectionDecorations.cs @@ -82,6 +82,8 @@ namespace OpenRA.Mods.Common.Traits.Render return DrawDecorations(self, wr); } + bool IRenderAboveShroud.SpatiallyPartitionable { get { return true; } } + IEnumerable DrawDecorations(Actor self, WorldRenderer wr) { var selected = self.World.Selection.Contains(self); diff --git a/OpenRA.Mods.Common/Traits/Render/WithDecoration.cs b/OpenRA.Mods.Common/Traits/Render/WithDecoration.cs index 7078689f81..54068d42e8 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithDecoration.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithDecoration.cs @@ -92,6 +92,9 @@ namespace OpenRA.Mods.Common.Traits.Render return Info.RequiresSelection ? RenderInner(self, wr) : SpriteRenderable.None; } + bool IRenderAboveShroud.SpatiallyPartitionable { get { return true; } } + bool IRenderAboveShroudWhenSelected.SpatiallyPartitionable { get { return true; } } + IEnumerable RenderInner(Actor self, WorldRenderer wr) { if (IsTraitDisabled || self.IsDead || !self.IsInWorld || Anim == null) diff --git a/OpenRA.Mods.Common/Traits/Render/WithRangeCircle.cs b/OpenRA.Mods.Common/Traits/Render/WithRangeCircle.cs index c2a21e4802..b7a8e07512 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithRangeCircle.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithRangeCircle.cs @@ -97,6 +97,8 @@ namespace OpenRA.Mods.Common.Traits.Render return RenderRangeCircle(self, wr); } + bool IRenderAboveShroudWhenSelected.SpatiallyPartitionable { get { return false; } } + void IRenderAboveWorld.RenderAboveWorld(Actor self, WorldRenderer wr) { if (Info.Visible == RangeCircleVisibility.Always && Visible) diff --git a/OpenRA.Mods.Common/Traits/Render/WithSpriteControlGroupDecoration.cs b/OpenRA.Mods.Common/Traits/Render/WithSpriteControlGroupDecoration.cs index f4abc84ab1..82489354a4 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithSpriteControlGroupDecoration.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithSpriteControlGroupDecoration.cs @@ -62,6 +62,8 @@ namespace OpenRA.Mods.Common.Traits.Render yield return r; } + bool IRenderAboveShroudWhenSelected.SpatiallyPartitionable { get { return true; } } + IEnumerable DrawControlGroup(Actor self, WorldRenderer wr, PaletteReference palette) { var group = self.World.Selection.GetControlGroupForActor(self); diff --git a/OpenRA.Mods.Common/Traits/Render/WithTextControlGroupDecoration.cs b/OpenRA.Mods.Common/Traits/Render/WithTextControlGroupDecoration.cs index de08f395a7..d9f482e906 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithTextControlGroupDecoration.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithTextControlGroupDecoration.cs @@ -79,6 +79,8 @@ namespace OpenRA.Mods.Common.Traits.Render yield return r; } + bool IRenderAboveShroudWhenSelected.SpatiallyPartitionable { get { return true; } } + IEnumerable DrawControlGroup(Actor self, WorldRenderer wr) { var group = self.World.Selection.GetControlGroupForActor(self); diff --git a/OpenRA.Mods.Common/Traits/Render/WithTextDecoration.cs b/OpenRA.Mods.Common/Traits/Render/WithTextDecoration.cs index 3aa22bbf4a..a3e3585ece 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithTextDecoration.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithTextDecoration.cs @@ -88,6 +88,8 @@ namespace OpenRA.Mods.Common.Traits.Render return Info.RequiresSelection ? RenderInner(self, wr) : SpriteRenderable.None; } + bool IRenderAboveShroudWhenSelected.SpatiallyPartitionable { get { return true; } } + IEnumerable RenderInner(Actor self, WorldRenderer wr) { if (IsTraitDisabled || self.IsDead || !self.IsInWorld)