Files
OpenRA/OpenRA.Mods.Common/Traits/World/TerrainGeometryOverlay.cs
Paul Chote e8794032e0 Introduce initial PPos plumbing.
PPos is best thought of as a cell grid applied in
screen space.  Multiple cells with different
terrain heights may be projected to the same PPos,
or to multiple PPos if they do not align with the
screen grid.

PPos coordinates are used primarily for map edge
checks and shroud / visibility queries.
2015-07-27 19:34:49 +01:00

102 lines
2.9 KiB
C#

#region Copyright & License Information
/*
* Copyright 2007-2015 The OpenRA Developers (see AUTHORS)
* 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. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Graphics;
using OpenRA.Mods.Common.Commands;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("Renders a debug overlay showing the terrain cells. Attach this to the world actor.")]
public class TerrainGeometryOverlayInfo : TraitInfo<TerrainGeometryOverlay> { }
public class TerrainGeometryOverlay : IPostRender, IWorldLoaded, IChatCommand
{
const string CommandName = "terrainoverlay";
const string CommandDesc = "Toggles the terrain geometry overlay";
public bool Enabled;
public void WorldLoaded(World w, WorldRenderer wr)
{
var console = w.WorldActor.TraitOrDefault<ChatCommands>();
var help = w.WorldActor.TraitOrDefault<HelpCommand>();
if (console == null || help == null)
return;
console.RegisterCommand(CommandName, this);
help.RegisterHelp(CommandName, CommandDesc);
}
public void InvokeCommand(string name, string arg)
{
if (name == CommandName)
Enabled ^= true;
}
public void RenderAfterWorld(WorldRenderer wr, Actor self)
{
if (!Enabled)
return;
var map = wr.World.Map;
var tileSet = wr.World.TileSet;
var lr = Game.Renderer.WorldLineRenderer;
var colors = wr.World.TileSet.HeightDebugColors;
var mouseCell = wr.Viewport.ViewToWorld(Viewport.LastMousePos).ToMPos(wr.World.Map);
foreach (var uv in wr.Viewport.AllVisibleCells.CandidateMapCoords)
{
var height = (int)map.MapHeight.Value[uv];
var tile = map.MapTiles.Value[uv];
var ti = tileSet.GetTileInfo(tile);
var ramp = ti != null ? (int)ti.RampType : 0;
var corners = map.CellCorners[ramp];
var color = corners.Select(c => colors[height + c.Z / 512]).ToArray();
var pos = map.CenterOfCell(uv.ToCPos(map));
var screen = corners.Select(c => wr.ScreenPxPosition(pos + c).ToFloat2()).ToArray();
if (uv == mouseCell)
lr.LineWidth = 3;
for (var i = 0; i < 4; i++)
{
var j = (i + 1) % 4;
lr.DrawLine(screen[i], screen[j], color[i], color[j]);
}
lr.LineWidth = 1;
}
// Projected cell coordinates for the current cell
var projectedCorners = map.CellCorners[0];
lr.LineWidth = 3;
foreach (var puv in map.ProjectedCellsCovering(mouseCell))
{
var pos = map.CenterOfCell(((MPos)puv).ToCPos(map));
var screen = projectedCorners.Select(c => wr.ScreenPxPosition(pos + c - new WVec(0, 0, pos.Z)).ToFloat2()).ToArray();
for (var i = 0; i < 4; i++)
{
var j = (i + 1) % 4;
lr.DrawLine(screen[i], screen[j], Color.Navy);
}
}
lr.LineWidth = 1;
}
}
}