Merge pull request #7577 from RoosterDragon/shroud-visibility-perf

Speed up shroud visibility updates.
This commit is contained in:
reaperrr
2015-03-22 22:38:41 +01:00
3 changed files with 38 additions and 23 deletions

View File

@@ -36,10 +36,7 @@ namespace OpenRA.Traits
{ {
cachedLocation = self.Location; cachedLocation = self.Location;
cachedDisabled = disabled; cachedDisabled = disabled;
Shroud.UpdateShroudGeneration(self.World.Players.Select(p => p.Shroud), self);
var shroud = self.World.Players.Select(p => p.Shroud);
foreach (var s in shroud)
s.UpdateShroudGeneration(self);
} }
} }

View File

@@ -33,9 +33,7 @@ namespace OpenRA.Traits
if (cachedLocation != self.Location) if (cachedLocation != self.Location)
{ {
cachedLocation = self.Location; cachedLocation = self.Location;
Shroud.UpdateVisibility(self.World.Players.Select(p => p.Shroud), self);
foreach (var s in self.World.Players.Select(p => p.Shroud))
s.UpdateVisibility(self);
} }
} }

View File

@@ -73,10 +73,10 @@ namespace OpenRA.Traits
generatedShroudCount = new CellLayer<short>(map); generatedShroudCount = new CellLayer<short>(map);
explored = new CellLayer<bool>(map); explored = new CellLayer<bool>(map);
self.World.ActorAdded += AddVisibility; self.World.ActorAdded += a => { CPos[] visible = null; AddVisibility(a, ref visible); };
self.World.ActorRemoved += RemoveVisibility; self.World.ActorRemoved += RemoveVisibility;
self.World.ActorAdded += AddShroudGeneration; self.World.ActorAdded += a => { CPos[] shrouded = null; AddShroudGeneration(a, ref shrouded); };
self.World.ActorRemoved += RemoveShroudGeneration; self.World.ActorRemoved += RemoveShroudGeneration;
fogVisibilities = Exts.Lazy(() => self.TraitsImplementing<IFogVisibilityModifier>().ToArray()); fogVisibilities = Exts.Lazy(() => self.TraitsImplementing<IFogVisibilityModifier>().ToArray());
@@ -98,6 +98,25 @@ namespace OpenRA.Traits
Hash += 1; Hash += 1;
} }
public static void UpdateVisibility(IEnumerable<Shroud> shrouds, Actor actor)
{
CPos[] visbility = null;
foreach (var shroud in shrouds)
shroud.UpdateVisibility(actor, ref visbility);
}
public static void UpdateShroudGeneration(IEnumerable<Shroud> shrouds, Actor actor)
{
CPos[] shrouded = null;
foreach (var shroud in shrouds)
shroud.UpdateShroudGeneration(actor, ref shrouded);
}
static CPos[] FindVisibleTiles(Actor actor, WRange range)
{
return GetVisOrigins(actor).SelectMany(o => FindVisibleTiles(actor.World, o, range)).Distinct().ToArray();
}
static IEnumerable<CPos> FindVisibleTiles(World world, CPos position, WRange radius) static IEnumerable<CPos> FindVisibleTiles(World world, CPos position, WRange radius)
{ {
var map = world.Map; var map = world.Map;
@@ -110,17 +129,15 @@ namespace OpenRA.Traits
yield return cell; yield return cell;
} }
void AddVisibility(Actor a) void AddVisibility(Actor a, ref CPos[] visible)
{ {
var rs = a.TraitOrDefault<RevealsShroud>(); var rs = a.TraitOrDefault<RevealsShroud>();
if (rs == null || !a.Owner.IsAlliedWith(self.Owner) || rs.Range == WRange.Zero) if (rs == null || !a.Owner.IsAlliedWith(self.Owner) || rs.Range == WRange.Zero)
return; return;
var origins = GetVisOrigins(a); // Lazily generate the visible tiles, allowing the caller to re-use them if desired.
var visible = origins.SelectMany(o => FindVisibleTiles(a.World, o, rs.Range)) visible = visible ?? FindVisibleTiles(a, rs.Range);
.Distinct().ToArray();
// Update visibility
foreach (var c in visible) foreach (var c in visible)
{ {
visibleCount[c]++; visibleCount[c]++;
@@ -147,24 +164,25 @@ namespace OpenRA.Traits
Invalidate(); Invalidate();
} }
public void UpdateVisibility(Actor a) void UpdateVisibility(Actor a, ref CPos[] visible)
{ {
// Actors outside the world don't have any vis // Actors outside the world don't have any vis
if (!a.IsInWorld) if (!a.IsInWorld)
return; return;
RemoveVisibility(a); RemoveVisibility(a);
AddVisibility(a); AddVisibility(a, ref visible);
} }
void AddShroudGeneration(Actor a) void AddShroudGeneration(Actor a, ref CPos[] shrouded)
{ {
var cs = a.TraitOrDefault<CreatesShroud>(); var cs = a.TraitOrDefault<CreatesShroud>();
if (cs == null || a.Owner.IsAlliedWith(self.Owner) || cs.Range == WRange.Zero) if (cs == null || a.Owner.IsAlliedWith(self.Owner) || cs.Range == WRange.Zero)
return; return;
var shrouded = GetVisOrigins(a).SelectMany(o => FindVisibleTiles(a.World, o, cs.Range)) // Lazily generate the shrouded tiles, allowing the caller to re-use them if desired.
.Distinct().ToArray(); shrouded = shrouded ?? FindVisibleTiles(a, cs.Range);
foreach (var c in shrouded) foreach (var c in shrouded)
generatedShroudCount[c]++; generatedShroudCount[c]++;
@@ -188,10 +206,10 @@ namespace OpenRA.Traits
Invalidate(); Invalidate();
} }
public void UpdateShroudGeneration(Actor a) void UpdateShroudGeneration(Actor a, ref CPos[] shrouded)
{ {
RemoveShroudGeneration(a); RemoveShroudGeneration(a);
AddShroudGeneration(a); AddShroudGeneration(a, ref shrouded);
} }
public void UpdatePlayerStance(World w, Player player, Stance oldStance, Stance newStance) public void UpdatePlayerStance(World w, Player player, Stance oldStance, Stance newStance)
@@ -201,8 +219,10 @@ namespace OpenRA.Traits
foreach (var a in w.Actors.Where(a => a.Owner == player)) foreach (var a in w.Actors.Where(a => a.Owner == player))
{ {
UpdateVisibility(a); CPos[] visible = null;
UpdateShroudGeneration(a); UpdateVisibility(a, ref visible);
CPos[] shrouded = null;
UpdateShroudGeneration(a, ref shrouded);
} }
} }