Lazily generate frozen actor renderables.
Previously actors that could be frozen under fog but were currently visible would be rendered by the frozen under fog system constantly in order to keep a copy of the renderables ready to go for the frozen counterpart when the actor became invisible. Instead, we now delay this extra rendering until the actor actually becomes invisible. This eliminates the wasted rendering to generate renderables that were never used.
This commit is contained in:
@@ -29,7 +29,6 @@ namespace OpenRA.Traits
|
|||||||
public readonly Rectangle Bounds;
|
public readonly Rectangle Bounds;
|
||||||
readonly Actor actor;
|
readonly Actor actor;
|
||||||
|
|
||||||
public IRenderable[] Renderables { private get; set; }
|
|
||||||
public Player Owner;
|
public Player Owner;
|
||||||
|
|
||||||
public ITooltipInfo TooltipInfo;
|
public ITooltipInfo TooltipInfo;
|
||||||
@@ -40,6 +39,8 @@ namespace OpenRA.Traits
|
|||||||
|
|
||||||
public bool Visible;
|
public bool Visible;
|
||||||
|
|
||||||
|
public bool IsRendering { get; private set; }
|
||||||
|
|
||||||
public FrozenActor(Actor self, MPos[] footprint, CellRegion footprintRegion, Shroud shroud)
|
public FrozenActor(Actor self, MPos[] footprint, CellRegion footprintRegion, Shroud shroud)
|
||||||
{
|
{
|
||||||
actor = self;
|
actor = self;
|
||||||
@@ -53,11 +54,16 @@ namespace OpenRA.Traits
|
|||||||
}
|
}
|
||||||
|
|
||||||
public uint ID { get { return actor.ActorID; } }
|
public uint ID { get { return actor.ActorID; } }
|
||||||
public bool IsValid { get { return Owner != null && HasRenderables; } }
|
public bool IsValid { get { return Owner != null; } }
|
||||||
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;
|
int flashTicks;
|
||||||
|
IRenderable[] renderables = NoRenderables;
|
||||||
|
bool needRenderables;
|
||||||
|
|
||||||
public void Tick(Shroud shroud)
|
public void Tick(Shroud shroud)
|
||||||
{
|
{
|
||||||
UpdateVisibility(shroud);
|
UpdateVisibility(shroud);
|
||||||
@@ -68,6 +74,8 @@ namespace OpenRA.Traits
|
|||||||
|
|
||||||
void UpdateVisibility(Shroud shroud)
|
void UpdateVisibility(Shroud shroud)
|
||||||
{
|
{
|
||||||
|
var wasVisible = Visible;
|
||||||
|
|
||||||
// We are doing the following LINQ manually to avoid allocating an extra delegate since this is a hot path.
|
// We are doing the following LINQ manually to avoid allocating an extra delegate since this is a hot path.
|
||||||
// Visible = !Footprint.Any(shroud.IsVisibleTest(FootprintRegion));
|
// Visible = !Footprint.Any(shroud.IsVisibleTest(FootprintRegion));
|
||||||
var isVisibleTest = shroud.IsVisibleTest(FootprintRegion);
|
var isVisibleTest = shroud.IsVisibleTest(FootprintRegion);
|
||||||
@@ -78,6 +86,9 @@ namespace OpenRA.Traits
|
|||||||
Visible = false;
|
Visible = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Visible && !wasVisible)
|
||||||
|
needRenderables = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Flash()
|
public void Flash()
|
||||||
@@ -87,20 +98,28 @@ namespace OpenRA.Traits
|
|||||||
|
|
||||||
public IEnumerable<IRenderable> Render(WorldRenderer wr)
|
public IEnumerable<IRenderable> Render(WorldRenderer wr)
|
||||||
{
|
{
|
||||||
if (Renderables == null)
|
if (needRenderables)
|
||||||
return SpriteRenderable.None;
|
{
|
||||||
|
needRenderables = false;
|
||||||
|
if (!actor.Destroyed)
|
||||||
|
{
|
||||||
|
IsRendering = true;
|
||||||
|
renderables = actor.Render(wr).ToArray();
|
||||||
|
IsRendering = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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 Renderables != null && Renderables.Any(); } }
|
public bool HasRenderables { get { return renderables.Any(); } }
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,7 +24,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, IVisibilityModifier, ITick, ITickRender, ISync
|
public class FrozenUnderFog : IRenderModifier, IVisibilityModifier, ITick, ISync
|
||||||
{
|
{
|
||||||
[Sync] public int VisibilityHash;
|
[Sync] public int VisibilityHash;
|
||||||
|
|
||||||
@@ -104,20 +104,9 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
initialized = true;
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TickRender(WorldRenderer wr, Actor self)
|
|
||||||
{
|
|
||||||
if (self.Destroyed || !initialized || !visible.Values.Any(v => v))
|
|
||||||
return;
|
|
||||||
|
|
||||||
var renderables = self.Render(wr).ToArray();
|
|
||||||
foreach (var player in self.World.Players)
|
|
||||||
if (visible[player])
|
|
||||||
frozen[player].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 IsVisible(self, self.World.RenderPlayer) ? r : SpriteRenderable.None;
|
return IsVisible(self, self.World.RenderPlayer) || (initialized && frozen[self.World.RenderPlayer].IsRendering) ? r : SpriteRenderable.None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user