Improve radar display for isometric maps.
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user