Add support for only rendering effects inside screen bounds

This commit is contained in:
Matthias Mailänder
2016-02-19 19:57:16 +01:00
committed by Paul Chote
parent 8ca43e3d6b
commit 1aebf9857c
5 changed files with 74 additions and 3 deletions

View File

@@ -20,5 +20,8 @@ namespace OpenRA.Effects
IEnumerable<IRenderable> Render(WorldRenderer r);
}
// Identifier interface for effects that are added to ScreenMap
public interface ISpatiallyPartitionable { }
public interface IEffectAboveShroud { IEnumerable<IRenderable> RenderAboveShroud(WorldRenderer wr); }
}

View File

@@ -110,7 +110,13 @@ namespace OpenRA.Graphics
if (World.OrderGenerator != null)
worldRenderables = worldRenderables.Concat(World.OrderGenerator.Render(this, World));
worldRenderables = worldRenderables.Concat(World.Effects.SelectMany(e => e.Render(this)));
// Unpartitioned effects
worldRenderables = worldRenderables.Concat(World.UnpartitionedEffects.SelectMany(e => e.Render(this)));
// Partitioned, currently on-screen effects
var effectRenderables = World.ScreenMap.EffectsInBox(Viewport.TopLeft, Viewport.BottomRight);
worldRenderables = worldRenderables.Concat(effectRenderables.SelectMany(e => e.Render(this)));
worldRenderables = worldRenderables.OrderBy(RenderableScreenZPositionComparisonKey);
Game.Renderer.WorldModelRenderer.BeginFrame();

View File

@@ -51,10 +51,15 @@ namespace OpenRA.Primitives
MutateBins(item, itemBounds[item] = bounds, addItem);
}
public void Remove(T item)
public bool Remove(T item)
{
MutateBins(item, itemBounds[item], removeItem);
Rectangle bounds;
if (!itemBounds.TryGetValue(item, out bounds))
return false;
MutateBins(item, bounds, removeItem);
itemBounds.Remove(item);
return true;
}
Dictionary<T, Rectangle> BinAt(int row, int col)

View File

@@ -13,6 +13,7 @@ using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Effects;
using OpenRA.Graphics;
using OpenRA.Primitives;
@@ -33,6 +34,7 @@ namespace OpenRA.Traits
readonly Func<Actor, bool> actorIsInWorld = a => a.IsInWorld;
readonly Cache<Player, SpatiallyPartitioned<FrozenActor>> partitionedFrozenActors;
readonly SpatiallyPartitioned<Actor> partitionedActors;
readonly SpatiallyPartitioned<IEffect> partitionedEffects;
WorldRenderer worldRenderer;
public ScreenMap(World world, ScreenMapInfo info)
@@ -43,6 +45,7 @@ namespace OpenRA.Traits
partitionedFrozenActors = new Cache<Player, SpatiallyPartitioned<FrozenActor>>(
_ => new SpatiallyPartitioned<FrozenActor>(width, height, info.BinSize));
partitionedActors = new SpatiallyPartitioned<Actor>(width, height, info.BinSize);
partitionedEffects = new SpatiallyPartitioned<IEffect>(width, height, info.BinSize);
}
public void WorldLoaded(World w, WorldRenderer wr) { worldRenderer = wr; }
@@ -88,6 +91,37 @@ namespace OpenRA.Traits
partitionedActors.Remove(a);
}
public void Add(IEffect effect, WPos position, Size size)
{
var screenPos = worldRenderer.ScreenPxPosition(position);
var screenBounds = new Rectangle(screenPos.X - size.Width / 2, screenPos.Y - size.Height / 2, size.Width, size.Height);
partitionedEffects.Add(effect, screenBounds);
}
public void Add(IEffect effect, WPos position, Sprite sprite)
{
var size = new Size((int)sprite.Size.X, (int)sprite.Size.Y);
Add(effect, position, size);
}
public void Update(IEffect effect, WPos position, Size size)
{
var screenPos = worldRenderer.ScreenPxPosition(position);
var screenBounds = new Rectangle(screenPos.X - size.Width / 2, screenPos.Y - size.Height / 2, size.Width, size.Height);
partitionedEffects.Update(effect, screenBounds);
}
public void Update(IEffect effect, WPos position, Sprite sprite)
{
var size = new Size((int)sprite.Size.X, (int)sprite.Size.Y);
Update(effect, position, size);
}
public void Remove(IEffect e)
{
partitionedEffects.Remove(e);
}
public IEnumerable<FrozenActor> FrozenActorsAt(Player viewer, int2 worldPx)
{
if (viewer == null)
@@ -120,6 +154,11 @@ namespace OpenRA.Traits
return ActorsInBox(RectWithCorners(a, b));
}
public IEnumerable<IEffect> EffectsInBox(int2 a, int2 b)
{
return partitionedEffects.InBox(RectWithCorners(a, b));
}
public IEnumerable<Actor> ActorsInBox(Rectangle r)
{
return partitionedActors.InBox(r).Where(actorIsInWorld);
@@ -130,6 +169,11 @@ namespace OpenRA.Traits
return FrozenActorsInBox(p, RectWithCorners(a, b));
}
public IEnumerable<IEffect> EffectsInBox(Rectangle r)
{
return partitionedEffects.InBox(r);
}
public IEnumerable<FrozenActor> FrozenActorsInBox(Player p, Rectangle r)
{
if (p == null)

View File

@@ -30,6 +30,7 @@ namespace OpenRA
internal readonly TraitDictionary TraitDict = new TraitDictionary();
readonly SortedDictionary<uint, Actor> actors = new SortedDictionary<uint, Actor>();
readonly List<IEffect> effects = new List<IEffect>();
readonly List<IEffect> unpartitionedEffects = new List<IEffect>();
readonly List<ISync> syncedEffects = new List<ISync>();
readonly Queue<Action<World>> frameEndActions = new Queue<Action<World>>();
@@ -285,6 +286,11 @@ namespace OpenRA
public void Add(IEffect e)
{
effects.Add(e);
var sp = e as ISpatiallyPartitionable;
if (sp == null)
unpartitionedEffects.Add(e);
var se = e as ISync;
if (se != null)
syncedEffects.Add(se);
@@ -293,6 +299,11 @@ namespace OpenRA
public void Remove(IEffect e)
{
effects.Remove(e);
var sp = e as ISpatiallyPartitionable;
if (sp == null)
unpartitionedEffects.Remove(e);
var se = e as ISync;
if (se != null)
syncedEffects.Remove(se);
@@ -301,6 +312,7 @@ namespace OpenRA
public void RemoveAll(Predicate<IEffect> predicate)
{
effects.RemoveAll(predicate);
unpartitionedEffects.RemoveAll(e => predicate((IEffect)e));
syncedEffects.RemoveAll(e => predicate((IEffect)e));
}
@@ -361,6 +373,7 @@ namespace OpenRA
public IEnumerable<Actor> Actors { get { return actors.Values; } }
public IEnumerable<IEffect> Effects { get { return effects; } }
public IEnumerable<IEffect> UnpartitionedEffects { get { return unpartitionedEffects; } }
public IEnumerable<ISync> SyncedEffects { get { return syncedEffects; } }
public Actor GetActorById(uint actorId)