From cbc090dd3873480a8f3b1d0cee982a9a3c97fdbc Mon Sep 17 00:00:00 2001 From: RoosterDragon Date: Sun, 6 Dec 2015 01:14:39 +0000 Subject: [PATCH] Ensure frozen actors are rendered on the first tick they become visible. The previous lazy rendering means the snapshot of the render state might be more up to date then when the frozen actor actually did become visible. Now, we take this snapshot as soon as needed. We still retain the performance of only doing this rendering when needed by avoiding extra rendering until the visibility cycles again. --- OpenRA.Game/Traits/Player/FrozenActorLayer.cs | 32 ++++++------------- .../Traits/Modifiers/FrozenUnderFog.cs | 29 +++++++++++++++-- 2 files changed, 36 insertions(+), 25 deletions(-) diff --git a/OpenRA.Game/Traits/Player/FrozenActorLayer.cs b/OpenRA.Game/Traits/Player/FrozenActorLayer.cs index 1e8a611385..55f6ad28c9 100644 --- a/OpenRA.Game/Traits/Player/FrozenActorLayer.cs +++ b/OpenRA.Game/Traits/Player/FrozenActorLayer.cs @@ -42,8 +42,11 @@ namespace OpenRA.Traits public bool Visible = true; public bool Shrouded { get; private set; } - public bool NeedRenderables { get; private set; } - public bool IsRendering { get; private set; } + public bool NeedRenderables { get; set; } + public IRenderable[] Renderables = NoRenderables; + static readonly IRenderable[] NoRenderables = new IRenderable[0]; + + int flashTicks; public FrozenActor(Actor self, PPos[] footprint, Shroud shroud, bool startsRevealed) { @@ -69,11 +72,6 @@ namespace OpenRA.Traits public ActorInfo Info { get { return actor.Info; } } public Actor Actor { get { return !actor.IsDead ? actor : null; } } - static readonly IRenderable[] NoRenderables = new IRenderable[0]; - - int flashTicks; - IRenderable[] renderables = NoRenderables; - public void Tick() { UpdateVisibility(); @@ -103,8 +101,7 @@ namespace OpenRA.Traits Shrouded = false; } - if (Visible && !wasVisible) - NeedRenderables = true; + NeedRenderables = Visible && !wasVisible; } public void Flash() @@ -114,31 +111,20 @@ namespace OpenRA.Traits public IEnumerable Render(WorldRenderer wr) { - if (NeedRenderables) - { - NeedRenderables = false; - if (!actor.Disposed) - { - IsRendering = true; - renderables = actor.Render(wr).ToArray(); - IsRendering = false; - } - } - if (Shrouded) return NoRenderables; if (flashTicks > 0 && flashTicks % 2 == 0) { var highlight = wr.Palette("highlight"); - return renderables.Concat(renderables.Where(r => !r.IsDecoration) + return Renderables.Concat(Renderables.Where(r => !r.IsDecoration) .Select(r => r.WithPalette(highlight))); } - return renderables; + return Renderables; } - public bool HasRenderables { get { return !Shrouded && renderables.Any(); } } + public bool HasRenderables { get { return !Shrouded && Renderables.Any(); } } public bool ShouldBeRemoved(Player owner) { diff --git a/OpenRA.Mods.Common/Traits/Modifiers/FrozenUnderFog.cs b/OpenRA.Mods.Common/Traits/Modifiers/FrozenUnderFog.cs index d1bb72ee2d..0017a7e605 100644 --- a/OpenRA.Mods.Common/Traits/Modifiers/FrozenUnderFog.cs +++ b/OpenRA.Mods.Common/Traits/Modifiers/FrozenUnderFog.cs @@ -27,7 +27,7 @@ namespace OpenRA.Mods.Common.Traits public object Create(ActorInitializer init) { return new FrozenUnderFog(init, this); } } - public class FrozenUnderFog : IRenderModifier, IDefaultVisibility, ITick, ISync + public class FrozenUnderFog : IRenderModifier, IDefaultVisibility, ITick, ITickRender, ISync { [Sync] public int VisibilityHash; @@ -41,6 +41,7 @@ namespace OpenRA.Mods.Common.Traits ITooltip tooltip; Health health; bool initialized; + bool isRendering; class FrozenState { @@ -143,11 +144,35 @@ namespace OpenRA.Mods.Common.Traits initialized = true; } + public void TickRender(WorldRenderer wr, Actor self) + { + if (!initialized) + return; + + IRenderable[] renderables = null; + foreach (var player in self.World.Players) + { + var frozen = stateByPlayer[player].FrozenActor; + if (!frozen.NeedRenderables) + continue; + + if (renderables == null) + { + isRendering = true; + renderables = self.Render(wr).ToArray(); + isRendering = false; + } + + frozen.NeedRenderables = false; + frozen.Renderables = renderables; + } + } + public IEnumerable ModifyRender(Actor self, WorldRenderer wr, IEnumerable r) { return IsVisible(self, self.World.RenderPlayer) || - (initialized && stateByPlayer[self.World.RenderPlayer].FrozenActor.IsRendering) ? + (initialized && isRendering) ? r : SpriteRenderable.None; } }