Update ScreenMap state in a single pass at the end of the tick.
This commit is contained in:
@@ -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];
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user