Merge pull request #10120 from RoosterDragon/gps-dot-perf

Fix broken GPS and frozen actor behaviour
This commit is contained in:
Oliver Brakmann
2015-12-13 18:28:12 +01:00
4 changed files with 77 additions and 45 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;
}
}

View File

@@ -37,14 +37,23 @@ namespace OpenRA.Mods.RA.Effects
readonly GpsDotInfo info;
readonly Animation anim;
readonly Dictionary<Player, bool> showToPlayer = new Dictionary<Player, bool>();
readonly Dictionary<Player, DotState> stateByPlayer = new Dictionary<Player, DotState>();
readonly Lazy<HiddenUnderFog> huf;
readonly Lazy<FrozenUnderFog> fuf;
readonly Lazy<Disguise> disguise;
readonly Lazy<Cloak> cloak;
readonly Cache<Player, FrozenActorLayer> frozen;
Lazy<HiddenUnderFog> huf;
Lazy<FrozenUnderFog> fuf;
Lazy<Disguise> disguise;
Lazy<Cloak> cloak;
Cache<Player, GpsWatcher> watcher;
Cache<Player, FrozenActorLayer> frozen;
class DotState
{
public readonly GpsWatcher Gps;
public bool IsTargetable;
public bool ShouldRender;
public DotState(GpsWatcher gps)
{
Gps = gps;
}
}
public GpsDot(Actor self, GpsDotInfo info)
{
@@ -60,19 +69,20 @@ namespace OpenRA.Mods.RA.Effects
disguise = Exts.Lazy(() => self.TraitOrDefault<Disguise>());
cloak = Exts.Lazy(() => self.TraitOrDefault<Cloak>());
watcher = new Cache<Player, GpsWatcher>(p => p.PlayerActor.Trait<GpsWatcher>());
frozen = new Cache<Player, FrozenActorLayer>(p => p.PlayerActor.Trait<FrozenActorLayer>());
showToPlayer = self.World.Players.ToDictionary(x => x, x => false);
stateByPlayer = self.World.Players.ToDictionary(p => p, p => new DotState(p.PlayerActor.Trait<GpsWatcher>()));
}
public bool IsDotVisible(Player toPlayer)
{
return showToPlayer[toPlayer];
return stateByPlayer[toPlayer].IsTargetable;
}
bool ShouldShowIndicator(Player toPlayer)
bool IsTargetableBy(Player toPlayer, out bool shouldRenderIndicator)
{
shouldRenderIndicator = false;
if (cloak.Value != null && cloak.Value.Cloaked)
return false;
@@ -81,19 +91,27 @@ namespace OpenRA.Mods.RA.Effects
if (huf.Value != null && !huf.Value.IsVisible(self, toPlayer)
&& toPlayer.Shroud.IsExplored(self.CenterPosition))
{
var f1 = FrozenActorForPlayer(toPlayer);
shouldRenderIndicator = f1 == null || !f1.HasRenderables;
return true;
}
if (fuf.Value == null)
return false;
var f = frozen[toPlayer].FromID(self.ActorID);
if (f == null)
var f2 = FrozenActorForPlayer(toPlayer);
if (f2 == null)
return false;
if (f.HasRenderables || f.NeedRenderables)
return false;
shouldRenderIndicator = !f2.HasRenderables;
return f.Visible && !f.Shrouded;
return f2.Visible && !f2.Shrouded;
}
FrozenActor FrozenActorForPlayer(Player player)
{
return frozen[player].FromID(self.ActorID);
}
public void Tick(World world)
@@ -106,14 +124,17 @@ namespace OpenRA.Mods.RA.Effects
foreach (var player in self.World.Players)
{
var gps = watcher[player];
showToPlayer[player] = (gps.Granted || gps.GrantedAllies) && ShouldShowIndicator(player);
var state = stateByPlayer[player];
var shouldRender = false;
var targetable = (state.Gps.Granted || state.Gps.GrantedAllies) && IsTargetableBy(player, out shouldRender);
state.IsTargetable = targetable;
state.ShouldRender = targetable && shouldRender;
}
}
public IEnumerable<IRenderable> Render(WorldRenderer wr)
{
if (self.World.RenderPlayer == null || !showToPlayer[self.World.RenderPlayer] || self.Disposed)
if (self.World.RenderPlayer == null || !stateByPlayer[self.World.RenderPlayer].ShouldRender || self.Disposed)
return SpriteRenderable.None;
var palette = wr.Palette(info.IndicatorPalettePrefix + self.Owner.InternalName);

View File

@@ -63,7 +63,7 @@ namespace OpenRA.Mods.RA.Traits
foreach (var i in atek.World.ActorsWithTrait<GpsWatcher>())
i.Trait.RefreshGranted();
if ((Granted || GrantedAllies) && atek.Owner.IsAlliedWith(atek.World.RenderPlayer))
if ((Granted || GrantedAllies) && atek.Owner.IsAlliedWith(Owner))
atek.Owner.Shroud.ExploreAll(atek.World);
}