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 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<IRenderable> 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)
{

View File

@@ -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<IRenderable> ModifyRender(Actor self, WorldRenderer wr, IEnumerable<IRenderable> r)
{
return
IsVisible(self, self.World.RenderPlayer) ||
(initialized && stateByPlayer[self.World.RenderPlayer].FrozenActor.IsRendering) ?
(initialized && isRendering) ?
r : SpriteRenderable.None;
}
}