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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool Contains(T item)
|
||||||
|
{
|
||||||
|
return itemBounds.ContainsKey(item);
|
||||||
|
}
|
||||||
|
|
||||||
Dictionary<T, Rectangle> BinAt(int row, int col)
|
Dictionary<T, Rectangle> BinAt(int row, int col)
|
||||||
{
|
{
|
||||||
return itemBoundsBins[row * cols + col];
|
return itemBoundsBins[row * cols + col];
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ namespace OpenRA.Traits
|
|||||||
public void Add(FrozenActor fa)
|
public void Add(FrozenActor fa)
|
||||||
{
|
{
|
||||||
frozenActorsById.Add(fa.ID, fa);
|
frozenActorsById.Add(fa.ID, fa);
|
||||||
world.ScreenMap.Add(owner, fa);
|
world.ScreenMap.AddOrUpdate(owner, fa);
|
||||||
partitionedFrozenActorIds.Add(fa.ID, FootprintBounds(fa));
|
partitionedFrozenActorIds.Add(fa.ID, FootprintBounds(fa));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,13 @@ namespace OpenRA.Traits
|
|||||||
readonly Cache<Player, SpatiallyPartitioned<FrozenActor>> partitionedFrozenActors;
|
readonly Cache<Player, SpatiallyPartitioned<FrozenActor>> partitionedFrozenActors;
|
||||||
readonly SpatiallyPartitioned<Actor> partitionedActors;
|
readonly SpatiallyPartitioned<Actor> partitionedActors;
|
||||||
readonly SpatiallyPartitioned<IEffect> partitionedEffects;
|
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;
|
WorldRenderer worldRenderer;
|
||||||
|
|
||||||
public ScreenMap(World world, ScreenMapInfo info)
|
public ScreenMap(World world, ScreenMapInfo info)
|
||||||
@@ -44,6 +51,10 @@ namespace OpenRA.Traits
|
|||||||
var height = world.Map.MapSize.Y * size.Height;
|
var height = world.Map.MapSize.Y * size.Height;
|
||||||
partitionedFrozenActors = new Cache<Player, SpatiallyPartitioned<FrozenActor>>(
|
partitionedFrozenActors = new Cache<Player, SpatiallyPartitioned<FrozenActor>>(
|
||||||
_ => new SpatiallyPartitioned<FrozenActor>(width, height, info.BinSize));
|
_ => 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);
|
partitionedActors = new SpatiallyPartitioned<Actor>(width, height, info.BinSize);
|
||||||
partitionedEffects = new SpatiallyPartitioned<IEffect>(width, height, info.BinSize);
|
partitionedEffects = new SpatiallyPartitioned<IEffect>(width, height, info.BinSize);
|
||||||
}
|
}
|
||||||
@@ -66,33 +77,30 @@ namespace OpenRA.Traits
|
|||||||
return bounds;
|
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)
|
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 (removeActors.Contains(a))
|
||||||
if (!bounds.Size.IsEmpty)
|
removeActors.Remove(a);
|
||||||
partitionedActors.Add(a, ActorBounds(a));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Update(Actor a)
|
addOrUpdateActors.Add(a);
|
||||||
{
|
|
||||||
var bounds = ActorBounds(a);
|
|
||||||
if (!bounds.Size.IsEmpty)
|
|
||||||
partitionedActors.Update(a, ActorBounds(a));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Remove(Actor a)
|
public void Remove(Actor a)
|
||||||
{
|
{
|
||||||
partitionedActors.Remove(a);
|
removeActors.Add(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Add(IEffect effect, WPos position, Size size)
|
public void Add(IEffect effect, WPos position, Size size)
|
||||||
@@ -192,6 +200,56 @@ namespace OpenRA.Traits
|
|||||||
return partitionedFrozenActors[p].InBox(r).Where(frozenActorIsValid);
|
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)
|
public IEnumerable<Rectangle> ItemBounds(Player viewer)
|
||||||
{
|
{
|
||||||
var bounds = partitionedActors.ItemBounds
|
var bounds = partitionedActors.ItemBounds
|
||||||
|
|||||||
@@ -191,7 +191,7 @@ namespace OpenRA
|
|||||||
{
|
{
|
||||||
ActorMap.AddInfluence(self, ios);
|
ActorMap.AddInfluence(self, ios);
|
||||||
ActorMap.AddPosition(self, ios);
|
ActorMap.AddPosition(self, ios);
|
||||||
ScreenMap.Add(self);
|
ScreenMap.AddOrUpdate(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateMaps(Actor self, IOccupySpace ios)
|
public void UpdateMaps(Actor self, IOccupySpace ios)
|
||||||
@@ -199,7 +199,7 @@ namespace OpenRA
|
|||||||
if (!self.IsInWorld)
|
if (!self.IsInWorld)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ScreenMap.Update(self);
|
ScreenMap.AddOrUpdate(self);
|
||||||
ActorMap.UpdatePosition(self, ios);
|
ActorMap.UpdatePosition(self, ios);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,6 +353,7 @@ namespace OpenRA
|
|||||||
ActorsWithTrait<ITick>().DoTimed(x => x.Trait.Tick(x.Actor), "Trait");
|
ActorsWithTrait<ITick>().DoTimed(x => x.Trait.Tick(x.Actor), "Trait");
|
||||||
|
|
||||||
effects.DoTimed(e => e.Tick(this), "Effect");
|
effects.DoTimed(e => e.Tick(this), "Effect");
|
||||||
|
ScreenMap.Tick();
|
||||||
}
|
}
|
||||||
|
|
||||||
while (frameEndActions.Count != 0)
|
while (frameEndActions.Count != 0)
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
public void SetVisualPosition(Actor self, WPos pos)
|
public void SetVisualPosition(Actor self, WPos pos)
|
||||||
{
|
{
|
||||||
CenterPosition = pos;
|
CenterPosition = pos;
|
||||||
self.World.ScreenMap.Update(self);
|
self.World.ScreenMap.AddOrUpdate(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetPosition(Actor self, WPos pos)
|
public void SetPosition(Actor self, WPos pos)
|
||||||
|
|||||||
Reference in New Issue
Block a user