99 lines
3.6 KiB
C#
99 lines
3.6 KiB
C#
#region Copyright & License Information
|
|
/*
|
|
* Copyright (c) The OpenRA Developers and Contributors
|
|
* This file is part of OpenRA, which is free software. It is made
|
|
* available to you under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation, either version 3 of
|
|
* the License, or (at your option) any later version. For more
|
|
* information, see COPYING.
|
|
*/
|
|
#endregion
|
|
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using OpenRA.Graphics;
|
|
using OpenRA.Primitives;
|
|
|
|
namespace OpenRA.Mods.Common.Graphics
|
|
{
|
|
public readonly struct BorderedRegionRenderable : IRenderable, IFinalizedRenderable
|
|
{
|
|
enum Corner { TopLeft, TopRight, BottomRight, BottomLeft }
|
|
|
|
// Maps a cell offset to the index of the corner (in the 'Corner' arrays in the MapGrid.CellRamp structs)
|
|
// from which a border should be drawn. The index of the end corner will be (cornerIndex + 1) % 4.
|
|
static readonly Dictionary<CVec, int> Offset2CornerIndex = new()
|
|
{
|
|
{ new CVec(0, -1), (int)Corner.TopLeft },
|
|
{ new CVec(1, 0), (int)Corner.TopRight },
|
|
{ new CVec(0, 1), (int)Corner.BottomRight },
|
|
{ new CVec(-1, 0), (int)Corner.BottomLeft },
|
|
};
|
|
|
|
readonly CPos[] region;
|
|
readonly Color color, contrastColor;
|
|
readonly float width, contrastWidth;
|
|
|
|
public BorderedRegionRenderable(CPos[] region, Color color, float width, Color contrastColor, float contrastWidth)
|
|
{
|
|
this.region = region;
|
|
this.color = color;
|
|
this.contrastColor = contrastColor;
|
|
this.width = width;
|
|
this.contrastWidth = contrastWidth;
|
|
}
|
|
|
|
readonly WPos IRenderable.Pos { get { return WPos.Zero; } }
|
|
readonly int IRenderable.ZOffset { get { return 0; } }
|
|
readonly bool IRenderable.IsDecoration { get { return true; } }
|
|
|
|
IRenderable IRenderable.WithZOffset(int newOffset) { return new BorderedRegionRenderable(region, color, width, contrastColor, contrastWidth); }
|
|
IRenderable IRenderable.OffsetBy(in WVec offset) { return new BorderedRegionRenderable(region, color, width, contrastColor, contrastWidth); }
|
|
IRenderable IRenderable.AsDecoration() { return this; }
|
|
|
|
IFinalizedRenderable IRenderable.PrepareRender(WorldRenderer wr) { return this; }
|
|
void IFinalizedRenderable.Render(WorldRenderer wr) { Draw(wr, region, color, width, contrastColor, contrastWidth); }
|
|
void IFinalizedRenderable.RenderDebugGeometry(WorldRenderer wr) { }
|
|
Rectangle IFinalizedRenderable.ScreenBounds(WorldRenderer wr) { return Rectangle.Empty; }
|
|
|
|
public static void Draw(WorldRenderer wr, CPos[] region, Color color, float width, Color constrastColor, float constrastWidth)
|
|
{
|
|
if (width == 0 && constrastWidth == 0)
|
|
return;
|
|
|
|
var map = wr.World.Map;
|
|
var cr = Game.Renderer.RgbaColorRenderer;
|
|
|
|
foreach (var c in region)
|
|
{
|
|
var mpos = c.ToMPos(map);
|
|
if (!map.Height.Contains(mpos) || wr.World.ShroudObscures(c))
|
|
continue;
|
|
|
|
var tile = map.Tiles[mpos];
|
|
var ti = map.Rules.TerrainInfo.GetTerrainInfo(tile);
|
|
var ramp = ti?.RampType ?? 0;
|
|
|
|
var corners = map.Grid.Ramps[ramp].Corners;
|
|
var pos = map.CenterOfCell(c) - new WVec(0, 0, map.Grid.Ramps[ramp].CenterHeightOffset);
|
|
|
|
foreach (var o in Offset2CornerIndex)
|
|
{
|
|
// If the neighboring cell is part of the region, don't draw a border between the cells.
|
|
if (region.Contains(c + o.Key))
|
|
continue;
|
|
|
|
var start = wr.Viewport.WorldToViewPx(wr.Screen3DPosition(pos + corners[o.Value]));
|
|
var end = wr.Viewport.WorldToViewPx(wr.Screen3DPosition(pos + corners[(o.Value + 1) % 4]));
|
|
|
|
if (constrastWidth > 0)
|
|
cr.DrawLine(start, end, constrastWidth, constrastColor);
|
|
|
|
if (width > 0)
|
|
cr.DrawLine(start, end, width, color);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|