Merge pull request #7748 from pchote/heightmap-input
Account for terrain height and slope when calculating order location.
This commit is contained in:
@@ -87,6 +87,29 @@ namespace OpenRA
|
|||||||
return r.Contains(p.ToPointF());
|
return r.Contains(p.ToPointF());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int WindingDirectionTest(int2 v0, int2 v1, int2 p)
|
||||||
|
{
|
||||||
|
return (v1.X - v0.X) * (p.Y - v0.Y) - (p.X - v0.X) * (v1.Y - v0.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool PolygonContains(this int2[] polygon, int2 p)
|
||||||
|
{
|
||||||
|
var windingNumber = 0;
|
||||||
|
|
||||||
|
for (var i = 0; i < polygon.Length; i++)
|
||||||
|
{
|
||||||
|
var tv = polygon[i];
|
||||||
|
var nv = polygon[(i + 1) % polygon.Length];
|
||||||
|
|
||||||
|
if (tv.Y <= p.Y && nv.Y > p.Y && WindingDirectionTest(tv, nv, p) > 0)
|
||||||
|
windingNumber++;
|
||||||
|
else if (tv.Y > p.Y && nv.Y <= p.Y && WindingDirectionTest(tv, nv, p) < 0)
|
||||||
|
windingNumber--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return windingNumber != 0;
|
||||||
|
}
|
||||||
|
|
||||||
public static bool HasModifier(this Modifiers k, Modifiers mod)
|
public static bool HasModifier(this Modifiers k, Modifiers mod)
|
||||||
{
|
{
|
||||||
return (k & mod) == mod;
|
return (k & mod) == mod;
|
||||||
|
|||||||
@@ -494,7 +494,7 @@ namespace OpenRA
|
|||||||
if (worldRenderer != null)
|
if (worldRenderer != null)
|
||||||
{
|
{
|
||||||
Renderer.BeginFrame(worldRenderer.Viewport.TopLeft, worldRenderer.Viewport.Zoom);
|
Renderer.BeginFrame(worldRenderer.Viewport.TopLeft, worldRenderer.Viewport.Zoom);
|
||||||
Sound.SetListenerPosition(worldRenderer.Position(worldRenderer.Viewport.CenterLocation));
|
Sound.SetListenerPosition(worldRenderer.Viewport.CenterPosition);
|
||||||
worldRenderer.Draw();
|
worldRenderer.Draw();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -105,9 +105,71 @@ namespace OpenRA.Graphics
|
|||||||
|
|
||||||
public CPos ViewToWorld(int2 view)
|
public CPos ViewToWorld(int2 view)
|
||||||
{
|
{
|
||||||
|
var world = worldRenderer.Viewport.ViewToWorldPx(view);
|
||||||
|
var map = worldRenderer.World.Map;
|
||||||
|
var ts = Game.ModData.Manifest.TileSize;
|
||||||
|
var candidates = CandidateMouseoverCells(world);
|
||||||
|
var tileSet = worldRenderer.World.TileSet;
|
||||||
|
|
||||||
|
foreach (var uv in candidates)
|
||||||
|
{
|
||||||
|
// Coarse filter to nearby cells
|
||||||
|
var p = map.CenterOfCell(uv.ToCPos(map.TileShape));
|
||||||
|
var s = worldRenderer.ScreenPxPosition(p);
|
||||||
|
if (Math.Abs(s.X - world.X) <= ts.Width && Math.Abs(s.Y - world.Y) <= ts.Height)
|
||||||
|
{
|
||||||
|
var ramp = 0;
|
||||||
|
if (map.Contains(uv))
|
||||||
|
{
|
||||||
|
var tile = map.MapTiles.Value[uv];
|
||||||
|
var ti = tileSet.GetTileInfo(tile);
|
||||||
|
if (ti != null)
|
||||||
|
ramp = ti.RampType;
|
||||||
|
}
|
||||||
|
|
||||||
|
var corners = map.CellCorners[ramp];
|
||||||
|
var pos = map.CenterOfCell(uv.ToCPos(map));
|
||||||
|
var screen = corners.Select(c => worldRenderer.ScreenPxPosition(pos + c)).ToArray();
|
||||||
|
|
||||||
|
if (screen.PolygonContains(world))
|
||||||
|
return uv.ToCPos(map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mouse is not directly over a cell (perhaps on a cliff)
|
||||||
|
// Try and find the closest cell
|
||||||
|
if (candidates.Any())
|
||||||
|
{
|
||||||
|
return candidates.OrderBy(uv =>
|
||||||
|
{
|
||||||
|
var p = map.CenterOfCell(uv.ToCPos(map.TileShape));
|
||||||
|
var s = worldRenderer.ScreenPxPosition(p);
|
||||||
|
var dx = Math.Abs(s.X - world.X);
|
||||||
|
var dy = Math.Abs(s.Y - world.Y);
|
||||||
|
|
||||||
|
return dx * dx + dy * dy;
|
||||||
|
}).First().ToCPos(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Something is very wrong, but lets return something that isn't completely bogus and hope the caller can recover
|
||||||
return worldRenderer.World.Map.CellContaining(worldRenderer.Position(ViewToWorldPx(view)));
|
return worldRenderer.World.Map.CellContaining(worldRenderer.Position(ViewToWorldPx(view)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary> Returns an unfiltered list of all cells that could potentially contain the mouse cursor</summary>
|
||||||
|
IEnumerable<MPos> CandidateMouseoverCells(int2 world)
|
||||||
|
{
|
||||||
|
var map = worldRenderer.World.Map;
|
||||||
|
var minPos = worldRenderer.Position(world);
|
||||||
|
|
||||||
|
// Find all the cells that could potentially have been clicked
|
||||||
|
var a = map.CellContaining(minPos - new WVec(1024, 0, 0)).ToMPos(map.TileShape);
|
||||||
|
var b = map.CellContaining(minPos + new WVec(512, 512 * maxGroundHeight, 0)).ToMPos(map.TileShape);
|
||||||
|
|
||||||
|
for (var v = b.V; v >= a.V; v--)
|
||||||
|
for (var u = b.U; u >= a.U; u--)
|
||||||
|
yield return new MPos(u, v);
|
||||||
|
}
|
||||||
|
|
||||||
public int2 ViewToWorldPx(int2 view) { return (1f / Zoom * view.ToFloat2()).ToInt2() + TopLeft; }
|
public int2 ViewToWorldPx(int2 view) { return (1f / Zoom * view.ToFloat2()).ToInt2() + TopLeft; }
|
||||||
public int2 WorldToViewPx(int2 world) { return (Zoom * (world - TopLeft).ToFloat2()).ToInt2(); }
|
public int2 WorldToViewPx(int2 world) { return (Zoom * (world - TopLeft).ToFloat2()).ToInt2(); }
|
||||||
|
|
||||||
|
|||||||
@@ -125,6 +125,42 @@ namespace OpenRA
|
|||||||
|
|
||||||
public class Map : IMap
|
public class Map : IMap
|
||||||
{
|
{
|
||||||
|
static readonly int[][] CellCornerHalfHeights = new int[][]
|
||||||
|
{
|
||||||
|
// Flat
|
||||||
|
new[] { 0, 0, 0, 0 },
|
||||||
|
|
||||||
|
// Slopes (two corners high)
|
||||||
|
new[] { 0, 0, 1, 1 },
|
||||||
|
new[] { 1, 0, 0, 1 },
|
||||||
|
new[] { 1, 1, 0, 0 },
|
||||||
|
new[] { 0, 1, 1, 0 },
|
||||||
|
|
||||||
|
// Slopes (one corner high)
|
||||||
|
new[] { 0, 0, 0, 1 },
|
||||||
|
new[] { 1, 0, 0, 0 },
|
||||||
|
new[] { 0, 1, 0, 0 },
|
||||||
|
new[] { 0, 0, 1, 0 },
|
||||||
|
|
||||||
|
// Slopes (three corners high)
|
||||||
|
new[] { 1, 0, 1, 1 },
|
||||||
|
new[] { 1, 1, 0, 1 },
|
||||||
|
new[] { 1, 1, 1, 0 },
|
||||||
|
new[] { 0, 1, 1, 1 },
|
||||||
|
|
||||||
|
// Slopes (two corners high, one corner double high)
|
||||||
|
new[] { 1, 0, 1, 2 },
|
||||||
|
new[] { 2, 1, 0, 1 },
|
||||||
|
new[] { 1, 2, 1, 0 },
|
||||||
|
new[] { 0, 1, 2, 1 },
|
||||||
|
|
||||||
|
// Slopes (two corners high, alternating)
|
||||||
|
new[] { 1, 0, 1, 0 },
|
||||||
|
new[] { 0, 1, 0, 1 },
|
||||||
|
new[] { 1, 0, 1, 0 },
|
||||||
|
new[] { 0, 1, 0, 1 }
|
||||||
|
};
|
||||||
|
|
||||||
public const int MaxTilesInCircleRange = 50;
|
public const int MaxTilesInCircleRange = 50;
|
||||||
public readonly TileShape TileShape;
|
public readonly TileShape TileShape;
|
||||||
TileShape IMap.TileShape
|
TileShape IMap.TileShape
|
||||||
@@ -219,6 +255,7 @@ namespace OpenRA
|
|||||||
public Ruleset Rules { get { return rules != null ? rules.Value : null; } }
|
public Ruleset Rules { get { return rules != null ? rules.Value : null; } }
|
||||||
public SequenceProvider SequenceProvider { get { return Rules.Sequences[Tileset]; } }
|
public SequenceProvider SequenceProvider { get { return Rules.Sequences[Tileset]; } }
|
||||||
|
|
||||||
|
public WVec[][] CellCorners { get; private set; }
|
||||||
[FieldLoader.Ignore] public CellRegion Cells;
|
[FieldLoader.Ignore] public CellRegion Cells;
|
||||||
|
|
||||||
public static Map FromTileset(TileSet tileset)
|
public static Map FromTileset(TileSet tileset)
|
||||||
@@ -394,6 +431,18 @@ namespace OpenRA
|
|||||||
CustomTerrain = new CellLayer<byte>(this);
|
CustomTerrain = new CellLayer<byte>(this);
|
||||||
foreach (var uv in Cells.MapCoords)
|
foreach (var uv in Cells.MapCoords)
|
||||||
CustomTerrain[uv] = byte.MaxValue;
|
CustomTerrain[uv] = byte.MaxValue;
|
||||||
|
|
||||||
|
var leftDelta = TileShape == TileShape.Diamond ? new WVec(-512, 0, 0) : new WVec(-512, -512, 0);
|
||||||
|
var topDelta = TileShape == TileShape.Diamond ? new WVec(0, -512, 0) : new WVec(512, -512, 0);
|
||||||
|
var rightDelta = TileShape == TileShape.Diamond ? new WVec(512, 0, 0) : new WVec(512, 512, 0);
|
||||||
|
var bottomDelta = TileShape == TileShape.Diamond ? new WVec(0, 512, 0) : new WVec(-512, 512, 0);
|
||||||
|
CellCorners = CellCornerHalfHeights.Select(ramp => new WVec[]
|
||||||
|
{
|
||||||
|
leftDelta + new WVec(0, 0, 512 * ramp[0]),
|
||||||
|
topDelta + new WVec(0, 0, 512 * ramp[1]),
|
||||||
|
rightDelta + new WVec(0, 0, 512 * ramp[2]),
|
||||||
|
bottomDelta + new WVec(0, 0, 512 * ramp[3])
|
||||||
|
}).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Ruleset PreloadRules()
|
public Ruleset PreloadRules()
|
||||||
@@ -641,7 +690,7 @@ namespace OpenRA
|
|||||||
// - ax + by adds (a - b) * 512 + 512 to u
|
// - ax + by adds (a - b) * 512 + 512 to u
|
||||||
// - ax + by adds (a + b) * 512 + 512 to v
|
// - ax + by adds (a + b) * 512 + 512 to v
|
||||||
var z = Contains(cell) ? 512 * MapHeight.Value[cell] : 0;
|
var z = Contains(cell) ? 512 * MapHeight.Value[cell] : 0;
|
||||||
return new WPos(512 * (cell.X - cell.Y + 1), 512 * (cell.X + cell.Y + 1), z);
|
return new WPos(512 * (cell.X - cell.Y), 512 * (cell.X + cell.Y + 1), z);
|
||||||
}
|
}
|
||||||
|
|
||||||
public WPos CenterOfSubCell(CPos cell, SubCell subCell)
|
public WPos CenterOfSubCell(CPos cell, SubCell subCell)
|
||||||
@@ -660,10 +709,10 @@ namespace OpenRA
|
|||||||
// Convert from world position to diamond cell position:
|
// Convert from world position to diamond cell position:
|
||||||
// (a) Subtract (512, 512) to move the rotation center to the middle of the corner cell
|
// (a) Subtract (512, 512) to move the rotation center to the middle of the corner cell
|
||||||
// (b) Rotate axes by -pi/4
|
// (b) Rotate axes by -pi/4
|
||||||
// (c) Add 512 to x (but not y) to realign the cell
|
// (c) Add (512, 512) to move back to the center of the cell
|
||||||
// (d) Divide by 1024 to find final cell coords
|
// (d) Divide by 1024 to find final cell coords
|
||||||
var u = (pos.Y + pos.X - 512) / 1024;
|
var u = (pos.Y + pos.X - 512) / 1024;
|
||||||
var v = (pos.Y - pos.X) / 1024;
|
var v = (pos.Y - pos.X - 512) / 1024;
|
||||||
return new CPos(u, v);
|
return new CPos(u, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ namespace OpenRA.Traits
|
|||||||
|
|
||||||
float GetIntensity()
|
float GetIntensity()
|
||||||
{
|
{
|
||||||
var cp = worldRenderer.Position(worldRenderer.Viewport.CenterLocation);
|
var cp = worldRenderer.Viewport.CenterPosition;
|
||||||
var intensity = 100 * 1024 * 1024 * shakeEffects.Sum(
|
var intensity = 100 * 1024 * 1024 * shakeEffects.Sum(
|
||||||
e => (float)e.Intensity / (e.Position - cp).LengthSquared);
|
e => (float)e.Intensity / (e.Position - cp).LengthSquared);
|
||||||
|
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ namespace OpenRA.Widgets
|
|||||||
// Place buildings, use support powers, and other non-unit things
|
// Place buildings, use support powers, and other non-unit things
|
||||||
if (!(World.OrderGenerator is UnitOrderGenerator))
|
if (!(World.OrderGenerator is UnitOrderGenerator))
|
||||||
{
|
{
|
||||||
ApplyOrders(World, xy, mi);
|
ApplyOrders(World, mi);
|
||||||
dragStart = dragEnd = null;
|
dragStart = dragEnd = null;
|
||||||
YieldMouseFocus(mi);
|
YieldMouseFocus(mi);
|
||||||
lastMousePosition = xy;
|
lastMousePosition = xy;
|
||||||
@@ -95,7 +95,7 @@ namespace OpenRA.Widgets
|
|||||||
!mi.Modifiers.HasModifier(Modifiers.Alt) && UnitOrderGenerator.InputOverridesSelection(World, xy, mi)))
|
!mi.Modifiers.HasModifier(Modifiers.Alt) && UnitOrderGenerator.InputOverridesSelection(World, xy, mi)))
|
||||||
{
|
{
|
||||||
// Order units instead of selecting
|
// Order units instead of selecting
|
||||||
ApplyOrders(World, xy, mi);
|
ApplyOrders(World, mi);
|
||||||
dragStart = dragEnd = null;
|
dragStart = dragEnd = null;
|
||||||
YieldMouseFocus(mi);
|
YieldMouseFocus(mi);
|
||||||
lastMousePosition = xy;
|
lastMousePosition = xy;
|
||||||
@@ -133,7 +133,7 @@ namespace OpenRA.Widgets
|
|||||||
if (useClassicMouseStyle)
|
if (useClassicMouseStyle)
|
||||||
World.Selection.Clear();
|
World.Selection.Clear();
|
||||||
|
|
||||||
ApplyOrders(World, xy, mi);
|
ApplyOrders(World, mi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,13 +159,13 @@ namespace OpenRA.Widgets
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApplyOrders(World world, int2 xy, MouseInput mi)
|
void ApplyOrders(World world, MouseInput mi)
|
||||||
{
|
{
|
||||||
if (world.OrderGenerator == null)
|
if (world.OrderGenerator == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var pos = worldRenderer.Position(xy);
|
var cell = worldRenderer.Viewport.ViewToWorld(mi.Location);
|
||||||
var orders = world.OrderGenerator.Order(world, world.Map.CellContaining(pos), mi).ToArray();
|
var orders = world.OrderGenerator.Order(world, cell, mi).ToArray();
|
||||||
world.PlayVoiceForOrders(orders);
|
world.PlayVoiceForOrders(orders);
|
||||||
|
|
||||||
var flashed = false;
|
var flashed = false;
|
||||||
@@ -184,8 +184,8 @@ namespace OpenRA.Widgets
|
|||||||
}
|
}
|
||||||
else if (o.TargetLocation != CPos.Zero)
|
else if (o.TargetLocation != CPos.Zero)
|
||||||
{
|
{
|
||||||
world.AddFrameEndTask(w => w.Add(
|
var pos = world.Map.CenterOfCell(cell);
|
||||||
new SpriteEffect(worldRenderer.Position(worldRenderer.Viewport.ViewToWorldPx(mi.Location)), world, "moveflsh", "moveflash")));
|
world.AddFrameEndTask(w => w.Add(new SpriteEffect(pos, world, "moveflsh", "moveflash")));
|
||||||
flashed = true;
|
flashed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -202,9 +202,7 @@ namespace OpenRA.Widgets
|
|||||||
if (SelectionBox != null)
|
if (SelectionBox != null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
var xy = worldRenderer.Viewport.ViewToWorldPx(screenPos);
|
var cell = worldRenderer.Viewport.ViewToWorld(screenPos);
|
||||||
var pos = worldRenderer.Position(xy);
|
|
||||||
var cell = World.Map.CellContaining(pos);
|
|
||||||
|
|
||||||
var mi = new MouseInput
|
var mi = new MouseInput
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -25,42 +25,6 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
public class TerrainGeometryOverlay : IRenderOverlay
|
public class TerrainGeometryOverlay : IRenderOverlay
|
||||||
{
|
{
|
||||||
readonly int[][] vertices = new int[][]
|
|
||||||
{
|
|
||||||
// Flat
|
|
||||||
new[] { 0, 0, 0, 0 },
|
|
||||||
|
|
||||||
// Slopes (two corners high)
|
|
||||||
new[] { 0, 0, 1, 1 },
|
|
||||||
new[] { 1, 0, 0, 1 },
|
|
||||||
new[] { 1, 1, 0, 0 },
|
|
||||||
new[] { 0, 1, 1, 0 },
|
|
||||||
|
|
||||||
// Slopes (one corner high)
|
|
||||||
new[] { 0, 0, 0, 1 },
|
|
||||||
new[] { 1, 0, 0, 0 },
|
|
||||||
new[] { 0, 1, 0, 0 },
|
|
||||||
new[] { 0, 0, 1, 0 },
|
|
||||||
|
|
||||||
// Slopes (three corners high)
|
|
||||||
new[] { 1, 0, 1, 1 },
|
|
||||||
new[] { 1, 1, 0, 1 },
|
|
||||||
new[] { 1, 1, 1, 0 },
|
|
||||||
new[] { 0, 1, 1, 1 },
|
|
||||||
|
|
||||||
// Slopes (two corners high, one corner double high)
|
|
||||||
new[] { 1, 0, 1, 2 },
|
|
||||||
new[] { 2, 1, 0, 1 },
|
|
||||||
new[] { 1, 2, 1, 0 },
|
|
||||||
new[] { 0, 1, 2, 1 },
|
|
||||||
|
|
||||||
// Slopes (two corners high, alternating)
|
|
||||||
new[] { 1, 0, 1, 0 },
|
|
||||||
new[] { 0, 1, 0, 1 },
|
|
||||||
new[] { 1, 0, 1, 0 },
|
|
||||||
new[] { 0, 1, 0, 1 }
|
|
||||||
};
|
|
||||||
|
|
||||||
readonly Lazy<DeveloperMode> devMode;
|
readonly Lazy<DeveloperMode> devMode;
|
||||||
|
|
||||||
public TerrainGeometryOverlay(Actor self)
|
public TerrainGeometryOverlay(Actor self)
|
||||||
@@ -73,54 +37,34 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
if (devMode.Value == null || !devMode.Value.ShowTerrainGeometry)
|
if (devMode.Value == null || !devMode.Value.ShowTerrainGeometry)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var ts = wr.World.Map.TileShape;
|
var map = wr.World.Map;
|
||||||
|
var tileSet = wr.World.TileSet;
|
||||||
|
var lr = Game.Renderer.WorldLineRenderer;
|
||||||
var colors = wr.World.TileSet.HeightDebugColors;
|
var colors = wr.World.TileSet.HeightDebugColors;
|
||||||
|
var mouseCell = wr.Viewport.ViewToWorld(Viewport.LastMousePos).ToMPos(wr.World.Map);
|
||||||
var leftDelta = ts == TileShape.Diamond ? new WVec(-512, 0, 0) : new WVec(-512, -512, 0);
|
|
||||||
var topDelta = ts == TileShape.Diamond ? new WVec(0, -512, 0) : new WVec(512, -512, 0);
|
|
||||||
var rightDelta = ts == TileShape.Diamond ? new WVec(512, 0, 0) : new WVec(512, 512, 0);
|
|
||||||
var bottomDelta = ts == TileShape.Diamond ? new WVec(0, 512, 0) : new WVec(-512, 512, 0);
|
|
||||||
|
|
||||||
foreach (var uv in wr.Viewport.VisibleCells.MapCoords)
|
foreach (var uv in wr.Viewport.VisibleCells.MapCoords)
|
||||||
{
|
{
|
||||||
var lr = Game.Renderer.WorldLineRenderer;
|
var height = (int)map.MapHeight.Value[uv];
|
||||||
var pos = wr.World.Map.CenterOfCell(uv.ToCPos(wr.World.Map));
|
var tile = map.MapTiles.Value[uv];
|
||||||
|
var ti = tileSet.GetTileInfo(tile);
|
||||||
|
var ramp = ti != null ? ti.RampType : 0;
|
||||||
|
|
||||||
var height = (int)wr.World.Map.MapHeight.Value[uv];
|
var corners = map.CellCorners[ramp];
|
||||||
var tile = wr.World.Map.MapTiles.Value[uv];
|
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();
|
||||||
|
|
||||||
TerrainTileInfo tileInfo = null;
|
if (uv == mouseCell)
|
||||||
|
lr.LineWidth = 3;
|
||||||
|
|
||||||
// TODO: This is a temporary workaround for our sloppy tileset definitions
|
for (var i = 0; i < 4; i++)
|
||||||
// (ra/td templates omit Clear tiles from templates)
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
tileInfo = wr.World.TileSet.Templates[tile.Type][tile.Index];
|
var j = (i + 1) % 4;
|
||||||
|
lr.DrawLine(screen[i], screen[j], color[i], color[j]);
|
||||||
}
|
}
|
||||||
catch (Exception) { }
|
|
||||||
|
|
||||||
if (tileInfo == null)
|
lr.LineWidth = 1;
|
||||||
continue;
|
|
||||||
|
|
||||||
var leftHeight = vertices[tileInfo.RampType][0];
|
|
||||||
var topHeight = vertices[tileInfo.RampType][1];
|
|
||||||
var rightHeight = vertices[tileInfo.RampType][2];
|
|
||||||
var bottomHeight = vertices[tileInfo.RampType][3];
|
|
||||||
|
|
||||||
var leftColor = colors[height + leftHeight];
|
|
||||||
var topColor = colors[height + topHeight];
|
|
||||||
var rightColor = colors[height + rightHeight];
|
|
||||||
var bottomColor = colors[height + bottomHeight];
|
|
||||||
|
|
||||||
var left = wr.ScreenPxPosition(pos + leftDelta + new WVec(0, 0, 512 * leftHeight)).ToFloat2();
|
|
||||||
var top = wr.ScreenPxPosition(pos + topDelta + new WVec(0, 0, 512 * topHeight)).ToFloat2();
|
|
||||||
var right = wr.ScreenPxPosition(pos + rightDelta + new WVec(0, 0, 512 * rightHeight)).ToFloat2();
|
|
||||||
var bottom = wr.ScreenPxPosition(pos + bottomDelta + new WVec(0, 0, 512 * bottomHeight)).ToFloat2();
|
|
||||||
|
|
||||||
lr.DrawLine(left, top, leftColor, topColor);
|
|
||||||
lr.DrawLine(top, right, topColor, rightColor);
|
|
||||||
lr.DrawLine(right, bottom, rightColor, bottomColor);
|
|
||||||
lr.DrawLine(bottom, left, bottomColor, leftColor);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user