Improve radar display for isometric maps.

This commit is contained in:
Paul Chote
2015-07-30 18:44:57 +01:00
parent 372d93994c
commit ed359c8aeb

View File

@@ -33,6 +33,10 @@ namespace OpenRA.Mods.Common.Widgets
readonly World world; readonly World world;
readonly WorldRenderer worldRenderer; readonly WorldRenderer worldRenderer;
readonly RadarPings radarPings; readonly RadarPings radarPings;
readonly bool isDiamond;
readonly int cellWidth;
readonly int previewWidth;
readonly int previewHeight;
readonly HashSet<PPos> dirtyShroudCells = new HashSet<PPos>(); readonly HashSet<PPos> dirtyShroudCells = new HashSet<PPos>();
@@ -59,6 +63,13 @@ namespace OpenRA.Mods.Common.Widgets
this.world = world; this.world = world;
this.worldRenderer = worldRenderer; this.worldRenderer = worldRenderer;
radarPings = world.WorldActor.TraitOrDefault<RadarPings>(); radarPings = world.WorldActor.TraitOrDefault<RadarPings>();
isDiamond = world.Map.TileShape == TileShape.Diamond;
cellWidth = isDiamond ? 2 : 1;
previewWidth = world.Map.MapSize.X;
previewHeight = world.Map.MapSize.Y;
if (isDiamond)
previewWidth = 2 * previewWidth - 1;
} }
public override void Initialize(WidgetArgs args) public override void Initialize(WidgetArgs args)
@@ -66,8 +77,7 @@ namespace OpenRA.Mods.Common.Widgets
base.Initialize(args); base.Initialize(args);
// The four layers are stored in a 2x2 grid within a single texture // The four layers are stored in a 2x2 grid within a single texture
var s = world.Map.MapSize; radarSheet = new Sheet(new Size(2 * previewWidth, 2 * previewHeight).NextPowerOf2());
radarSheet = new Sheet(new Size(2 * s.X, 2 * s.Y).NextPowerOf2());
radarSheet.CreateBuffer(); radarSheet.CreateBuffer();
radarData = radarSheet.GetData(); radarData = radarSheet.GetData();
@@ -93,6 +103,8 @@ namespace OpenRA.Mods.Common.Widgets
var projectedBottom = map.Bounds.Bottom; var projectedBottom = map.Bounds.Bottom;
var top = int.MaxValue; var top = int.MaxValue;
var bottom = int.MinValue; var bottom = int.MinValue;
var left = map.Bounds.Left * cellWidth;
var right = map.Bounds.Right * cellWidth;
for (var x = projectedLeft; x < projectedRight; x++) for (var x = projectedLeft; x < projectedRight; x++)
{ {
@@ -105,18 +117,15 @@ namespace OpenRA.Mods.Common.Widgets
bottom = Math.Max(bottom, allBottom.MinBy(uv => uv.V).V); bottom = Math.Max(bottom, allBottom.MinBy(uv => uv.V).V);
} }
// Map bounds in cell space var b = Rectangle.FromLTRB(left, top, right, bottom);
var b = Rectangle.FromLTRB(projectedLeft, top, projectedRight, bottom);
var rb = RenderBounds; var rb = RenderBounds;
previewScale = Math.Min(rb.Width * 1f / b.Width, rb.Height * 1f / b.Height); previewScale = Math.Min(rb.Width * 1f / b.Width, rb.Height * 1f / b.Height);
previewOrigin = new int2((int)((rb.Width - previewScale * b.Width) / 2), (int)((rb.Height - previewScale * b.Height) / 2)); previewOrigin = new int2((int)((rb.Width - previewScale * b.Width) / 2), (int)((rb.Height - previewScale * b.Height) / 2));
mapRect = new Rectangle(previewOrigin.X, previewOrigin.Y, (int)(previewScale * b.Width), (int)(previewScale * b.Height)); mapRect = new Rectangle(previewOrigin.X, previewOrigin.Y, (int)(previewScale * b.Width), (int)(previewScale * b.Height));
var s = world.Map.MapSize;
terrainSprite = new Sprite(radarSheet, b, TextureChannel.Alpha); terrainSprite = new Sprite(radarSheet, b, TextureChannel.Alpha);
shroudSprite = new Sprite(radarSheet, new Rectangle(b.Location + new Size(s.X, 0), b.Size), TextureChannel.Alpha); shroudSprite = new Sprite(radarSheet, new Rectangle(b.Location + new Size(previewWidth, 0), b.Size), TextureChannel.Alpha);
actorSprite = new Sprite(radarSheet, new Rectangle(b.Location + new Size(0, s.Y), b.Size), TextureChannel.Alpha); actorSprite = new Sprite(radarSheet, new Rectangle(b.Location + new Size(0, previewHeight), b.Size), TextureChannel.Alpha);
} }
void UpdateTerrainCell(CPos cell) void UpdateTerrainCell(CPos cell)
@@ -127,14 +136,15 @@ namespace OpenRA.Mods.Common.Widgets
return; return;
var custom = world.Map.CustomTerrain[uv]; var custom = world.Map.CustomTerrain[uv];
Color color; int leftColor, rightColor;
if (custom == byte.MaxValue) if (custom == byte.MaxValue)
{ {
var type = world.TileSet.GetTileInfo(world.Map.MapTiles.Value[uv]); var type = world.TileSet.GetTileInfo(world.Map.MapTiles.Value[uv]);
color = type != null ? type.LeftColor : Color.Black; leftColor = type != null ? type.LeftColor.ToArgb() : Color.Black.ToArgb();
rightColor = type != null ? type.RightColor.ToArgb() : Color.Black.ToArgb();
} }
else else
color = world.TileSet[custom].Color; leftColor = rightColor = world.TileSet[custom].Color.ToArgb();
var stride = radarSheet.Size.Width; var stride = radarSheet.Size.Width;
@@ -143,32 +153,55 @@ namespace OpenRA.Mods.Common.Widgets
fixed (byte* colorBytes = &radarData[0]) fixed (byte* colorBytes = &radarData[0])
{ {
var colors = (int*)colorBytes; var colors = (int*)colorBytes;
colors[uv.V * stride + uv.U] = color.ToArgb(); if (isDiamond)
{
// Odd rows are shifted right by 1px
var dx = uv.V & 1;
if (uv.U + dx > 0)
colors[uv.V * stride + 2 * uv.U + dx - 1] = leftColor;
if (2 * uv.U + dx < stride)
colors[uv.V * stride + 2 * uv.U + dx] = rightColor;
}
else
colors[uv.V * stride + uv.U] = leftColor;
} }
} }
} }
void UpdateShroudCell(PPos projectedCell) void UpdateShroudCell(PPos puv)
{ {
var stride = radarSheet.Size.Width;
var dx = world.Map.MapSize.X;
var color = 0; var color = 0;
var rp = world.RenderPlayer; var rp = world.RenderPlayer;
if (rp != null) if (rp != null)
{ {
if (!rp.Shroud.IsExplored(projectedCell)) if (!rp.Shroud.IsExplored(puv))
color = Color.Black.ToArgb(); color = Color.Black.ToArgb();
else if (!rp.Shroud.IsVisible(projectedCell)) else if (!rp.Shroud.IsVisible(puv))
color = Color.FromArgb(128, Color.Black).ToArgb(); color = Color.FromArgb(128, Color.Black).ToArgb();
} }
var stride = radarSheet.Size.Width;
unsafe unsafe
{ {
fixed (byte* colorBytes = &radarData[0]) fixed (byte* colorBytes = &radarData[0])
{ {
var colors = (int*)colorBytes; var colors = (int*)colorBytes;
colors[projectedCell.V * stride + projectedCell.U + dx] = color; foreach (var uv in world.Map.Unproject(puv))
{
if (isDiamond)
{
// Odd rows are shifted right by 1px
var dx = uv.V & 1;
if (uv.U + dx > 0)
colors[uv.V * stride + 2 * uv.U + dx - 1 + previewWidth] = color;
if (2 * uv.U + dx < stride)
colors[uv.V * stride + 2 * uv.U + dx + previewWidth] = color;
}
else
colors[uv.V * stride + uv.U + previewWidth] = color;
}
} }
} }
} }
@@ -328,9 +361,7 @@ namespace OpenRA.Mods.Common.Widgets
// The actor layer is updated every tick // The actor layer is updated every tick
var stride = radarSheet.Size.Width; var stride = radarSheet.Size.Width;
var dy = world.Map.MapSize.Y; Array.Clear(radarData, 4 * actorSprite.Bounds.Top * stride, 4 * actorSprite.Bounds.Height * stride);
Array.Clear(radarData, 4 * (actorSprite.Bounds.Top * stride + actorSprite.Bounds.Left), 4 * actorSprite.Bounds.Height * stride);
unsafe unsafe
{ {
@@ -345,10 +376,20 @@ namespace OpenRA.Mods.Common.Widgets
foreach (var cell in t.Trait.RadarSignatureCells(t.Actor)) foreach (var cell in t.Trait.RadarSignatureCells(t.Actor))
{ {
var uv = cell.First.ToMPos(world.Map); var uv = cell.First.ToMPos(world.Map.TileShape);
var color = cell.Second.ToArgb();
if (isDiamond)
{
// Odd rows are shifted right by 1px
var dx = uv.V & 1;
if (uv.U + dx > 0)
colors[(uv.V + previewHeight) * stride + 2 * uv.U + dx - 1] = color;
if (world.Map.Bounds.Contains(uv.U, uv.V)) if (2 * uv.U + dx < stride)
colors[(uv.V + dy) * stride + uv.U] = cell.Second.ToArgb(); colors[(uv.V + previewHeight) * stride + 2 * uv.U + dx] = color;
}
else
colors[(uv.V + previewHeight) * stride + uv.U] = color;
} }
} }
} }
@@ -382,8 +423,14 @@ namespace OpenRA.Mods.Common.Widgets
int2 CellToMinimapPixel(CPos p) int2 CellToMinimapPixel(CPos p)
{ {
var uv = p.ToMPos(world.Map); var uv = p.ToMPos(world.Map);
var mapOffset = new float2(uv.U - world.Map.Bounds.Left, uv.V - world.Map.Bounds.Top); var dx = (int)(previewScale * cellWidth * (uv.U - world.Map.Bounds.Left));
return new int2(mapRect.X, mapRect.Y) + (previewScale * mapOffset).ToInt2(); var dy = (int)(previewScale * (uv.V - world.Map.Bounds.Top));
// Odd rows are shifted right by 1px
if ((uv.V & 1) == 1)
dx += 1;
return new int2(mapRect.X + dx, mapRect.Y + dy);
} }
CPos MinimapPixelToCell(int2 p) CPos MinimapPixelToCell(int2 p)
@@ -391,7 +438,7 @@ namespace OpenRA.Mods.Common.Widgets
var viewOrigin = new float2(mapRect.X, mapRect.Y); var viewOrigin = new float2(mapRect.X, mapRect.Y);
var mapOrigin = new float2(world.Map.Bounds.Left, world.Map.Bounds.Top); var mapOrigin = new float2(world.Map.Bounds.Left, world.Map.Bounds.Top);
var fcell = mapOrigin + (1f / previewScale) * (p - viewOrigin); var fcell = mapOrigin + (1f / previewScale) * (p - viewOrigin);
return new MPos((int)fcell.X, (int)fcell.Y).ToCPos(world.Map); return new MPos((int)fcell.X / 2, (int)fcell.Y).ToCPos(world.Map);
} }
} }
} }