Update ScreenMap state in a single pass at the end of the tick.

This commit is contained in:
Paul Chote
2017-12-05 17:37:18 +00:00
committed by reaperrr
parent 373aaee004
commit 46f6263061
5 changed files with 82 additions and 18 deletions

View File

@@ -62,6 +62,11 @@ namespace OpenRA.Primitives
return true;
}
public bool Contains(T item)
{
return itemBounds.ContainsKey(item);
}
Dictionary<T, Rectangle> BinAt(int row, int col)
{
return itemBoundsBins[row * cols + col];

View File

@@ -210,7 +210,7 @@ namespace OpenRA.Traits
public void Add(FrozenActor fa)
{
frozenActorsById.Add(fa.ID, fa);
world.ScreenMap.Add(owner, fa);
world.ScreenMap.AddOrUpdate(owner, fa);
partitionedFrozenActorIds.Add(fa.ID, FootprintBounds(fa));
}

View File

@@ -35,6 +35,13 @@ namespace OpenRA.Traits
readonly Cache<Player, SpatiallyPartitioned<FrozenActor>> partitionedFrozenActors;
readonly SpatiallyPartitioned<Actor> partitionedActors;
readonly SpatiallyPartitioned<IEffect> partitionedEffects;
// Updates are done in one pass to ensure all bound changes have been applied
readonly HashSet<Actor> addOrUpdateActors = new HashSet<Actor>();
readonly HashSet<Actor> removeActors = new HashSet<Actor>();
readonly Cache<Player, HashSet<FrozenActor>> addOrUpdateFrozenActors;
readonly Cache<Player, HashSet<FrozenActor>> removeFrozenActors;
WorldRenderer worldRenderer;
public ScreenMap(World world, ScreenMapInfo info)
@@ -44,6 +51,10 @@ namespace OpenRA.Traits
var height = world.Map.MapSize.Y * size.Height;
partitionedFrozenActors = new Cache<Player, SpatiallyPartitioned<FrozenActor>>(
_ => new SpatiallyPartitioned<FrozenActor>(width, height, info.BinSize));
addOrUpdateFrozenActors = new Cache<Player, HashSet<FrozenActor>>(_ => new HashSet<FrozenActor>());
removeFrozenActors = new Cache<Player, HashSet<FrozenActor>>(_ => new HashSet<FrozenActor>());
partitionedActors = new SpatiallyPartitioned<Actor>(width, height, info.BinSize);
partitionedEffects = new SpatiallyPartitioned<IEffect>(width, height, info.BinSize);
}
@@ -66,33 +77,30 @@ namespace OpenRA.Traits
return bounds;
}
public void Add(Player viewer, FrozenActor fa)
public void AddOrUpdate(Player viewer, FrozenActor fa)
{
partitionedFrozenActors[viewer].Add(fa, FrozenActorBounds(fa));
if (removeFrozenActors[viewer].Contains(fa))
removeFrozenActors[viewer].Remove(fa);
addOrUpdateFrozenActors[viewer].Add(fa);
}
public void Remove(Player viewer, FrozenActor fa)
{
partitionedFrozenActors[viewer].Remove(fa);
removeFrozenActors[viewer].Add(fa);
}
public void Add(Actor a)
public void AddOrUpdate(Actor a)
{
var bounds = ActorBounds(a);
if (!bounds.Size.IsEmpty)
partitionedActors.Add(a, ActorBounds(a));
}
if (removeActors.Contains(a))
removeActors.Remove(a);
public void Update(Actor a)
{
var bounds = ActorBounds(a);
if (!bounds.Size.IsEmpty)
partitionedActors.Update(a, ActorBounds(a));
addOrUpdateActors.Add(a);
}
public void Remove(Actor a)
{
partitionedActors.Remove(a);
removeActors.Add(a);
}
public void Add(IEffect effect, WPos position, Size size)
@@ -192,6 +200,56 @@ namespace OpenRA.Traits
return partitionedFrozenActors[p].InBox(r).Where(frozenActorIsValid);
}
public void Tick()
{
foreach (var a in addOrUpdateActors)
{
var bounds = ActorBounds(a);
if (!bounds.Size.IsEmpty)
{
if (partitionedActors.Contains(a))
partitionedActors.Update(a, bounds);
else
partitionedActors.Add(a, bounds);
}
else
partitionedActors.Remove(a);
}
foreach (var a in removeActors)
partitionedActors.Remove(a);
addOrUpdateActors.Clear();
removeActors.Clear();
foreach (var kv in addOrUpdateFrozenActors)
{
foreach (var fa in kv.Value)
{
var bounds = FrozenActorBounds(fa);
if (!bounds.Size.IsEmpty)
{
if (partitionedFrozenActors[kv.Key].Contains(fa))
partitionedFrozenActors[kv.Key].Update(fa, bounds);
else
partitionedFrozenActors[kv.Key].Add(fa, bounds);
}
else
partitionedFrozenActors[kv.Key].Remove(fa);
}
kv.Value.Clear();
}
foreach (var kv in removeFrozenActors)
{
foreach (var fa in kv.Value)
partitionedFrozenActors[kv.Key].Remove(fa);
kv.Value.Clear();
}
}
public IEnumerable<Rectangle> ItemBounds(Player viewer)
{
var bounds = partitionedActors.ItemBounds

View File

@@ -191,7 +191,7 @@ namespace OpenRA
{
ActorMap.AddInfluence(self, ios);
ActorMap.AddPosition(self, ios);
ScreenMap.Add(self);
ScreenMap.AddOrUpdate(self);
}
public void UpdateMaps(Actor self, IOccupySpace ios)
@@ -199,7 +199,7 @@ namespace OpenRA
if (!self.IsInWorld)
return;
ScreenMap.Update(self);
ScreenMap.AddOrUpdate(self);
ActorMap.UpdatePosition(self, ios);
}
@@ -353,6 +353,7 @@ namespace OpenRA
ActorsWithTrait<ITick>().DoTimed(x => x.Trait.Tick(x.Actor), "Trait");
effects.DoTimed(e => e.Tick(this), "Effect");
ScreenMap.Tick();
}
while (frameEndActions.Count != 0)

View File

@@ -105,7 +105,7 @@ namespace OpenRA.Mods.Common.Traits
public void SetVisualPosition(Actor self, WPos pos)
{
CenterPosition = pos;
self.World.ScreenMap.Update(self);
self.World.ScreenMap.AddOrUpdate(self);
}
public void SetPosition(Actor self, WPos pos)