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.
This commit is contained in:
RoosterDragon
2015-12-06 01:14:39 +00:00
parent 87d35a75da
commit cbc090dd38
2 changed files with 36 additions and 25 deletions

View File

@@ -42,8 +42,11 @@ namespace OpenRA.Traits
public bool Visible = true; public bool Visible = true;
public bool Shrouded { get; private set; } public bool Shrouded { get; private set; }
public bool NeedRenderables { get; private set; } public bool NeedRenderables { get; set; }
public bool IsRendering { get; private set; } public IRenderable[] Renderables = NoRenderables;
static readonly IRenderable[] NoRenderables = new IRenderable[0];
int flashTicks;
public FrozenActor(Actor self, PPos[] footprint, Shroud shroud, bool startsRevealed) 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 ActorInfo Info { get { return actor.Info; } }
public Actor Actor { get { return !actor.IsDead ? actor : null; } } public Actor Actor { get { return !actor.IsDead ? actor : null; } }
static readonly IRenderable[] NoRenderables = new IRenderable[0];
int flashTicks;
IRenderable[] renderables = NoRenderables;
public void Tick() public void Tick()
{ {
UpdateVisibility(); UpdateVisibility();
@@ -103,8 +101,7 @@ namespace OpenRA.Traits
Shrouded = false; Shrouded = false;
} }
if (Visible && !wasVisible) NeedRenderables = Visible && !wasVisible;
NeedRenderables = true;
} }
public void Flash() public void Flash()
@@ -114,31 +111,20 @@ namespace OpenRA.Traits
public IEnumerable<IRenderable> Render(WorldRenderer wr) public IEnumerable<IRenderable> Render(WorldRenderer wr)
{ {
if (NeedRenderables)
{
NeedRenderables = false;
if (!actor.Disposed)
{
IsRendering = true;
renderables = actor.Render(wr).ToArray();
IsRendering = false;
}
}
if (Shrouded) if (Shrouded)
return NoRenderables; return NoRenderables;
if (flashTicks > 0 && flashTicks % 2 == 0) if (flashTicks > 0 && flashTicks % 2 == 0)
{ {
var highlight = wr.Palette("highlight"); 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))); .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) public bool ShouldBeRemoved(Player owner)
{ {

View File

@@ -27,7 +27,7 @@ namespace OpenRA.Mods.Common.Traits
public object Create(ActorInitializer init) { return new FrozenUnderFog(init, this); } 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; [Sync] public int VisibilityHash;
@@ -41,6 +41,7 @@ namespace OpenRA.Mods.Common.Traits
ITooltip tooltip; ITooltip tooltip;
Health health; Health health;
bool initialized; bool initialized;
bool isRendering;
class FrozenState class FrozenState
{ {
@@ -143,11 +144,35 @@ namespace OpenRA.Mods.Common.Traits
initialized = true; 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<IRenderable> ModifyRender(Actor self, WorldRenderer wr, IEnumerable<IRenderable> r) public IEnumerable<IRenderable> ModifyRender(Actor self, WorldRenderer wr, IEnumerable<IRenderable> r)
{ {
return return
IsVisible(self, self.World.RenderPlayer) || IsVisible(self, self.World.RenderPlayer) ||
(initialized && stateByPlayer[self.World.RenderPlayer].FrozenActor.IsRendering) ? (initialized && isRendering) ?
r : SpriteRenderable.None; r : SpriteRenderable.None;
} }
} }