Skip to content

Commit

Permalink
Disable "see-through" cell cursor behaviour for ground flattening tool
Browse files Browse the repository at this point in the history
  • Loading branch information
Rampastring committed Dec 10, 2023
1 parent 8568cd8 commit cdcc6cf
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 10 deletions.
69 changes: 60 additions & 9 deletions src/TSMapEditor/GameMath/CellMath.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.Xna.Framework;
using System;
using TSMapEditor.Models;

namespace TSMapEditor.GameMath
Expand Down Expand Up @@ -75,7 +76,14 @@ public static Point2D CellCoordsFromPixelCoords_2D(Point2D pixelCoords, Map map)
return new Point2D(cx, cy);
}

public static Point2D CellCoordsFromPixelCoords(Point2D pixelCoords, Map map)
/// <summary>
/// Calculates and returns the game-logical coordinates of a cell at given pixel-based coordinates in the world.
/// </summary>
/// <param name="pixelCoords">The pixel-based location.</param>
/// <param name="map">The map.</param>
/// <param name="seethrough">Whether we should "see through" walls in the game world, such as cliffs,
/// allowing us to reach cells that are behind cliffs.</param>
public static Point2D CellCoordsFromPixelCoords(Point2D pixelCoords, Map map, bool seethrough = true)
{
Point2D coords2D = CellCoordsFromPixelCoords_2D(pixelCoords, map);

Expand All @@ -85,31 +93,74 @@ public static Point2D CellCoordsFromPixelCoords(Point2D pixelCoords, Map map)
Point2D nearestCenterCoords = new Point2D(-1, -1);
float nearestDistance = float.MaxValue;

const int threshold = 1;
const int scanSize = 3;


// Take isometric perspective into account
Vector2 worldCoordsNonIsometric = new Point2D(pixelCoords.X / 2, pixelCoords.Y).ToXNAVector();

// Scan all cells that are deemed to be "close enough" to the initial cell
// to see if our cursor is on the cell
for (int y = -3; y <= 3; y++)
for (int y = -scanSize; y <= scanSize; y++)
{
for (int x = -3; x <= 3; x++)
for (int x = -scanSize; x <= scanSize; x++)
{
// traverse height
for (int i = 0; i < 14; i++)
for (int i = 0; i <= Constants.MaxMapHeightLevel; i++)
{
var otherCellCoords = coords2D + new Point2D(x, y) + new Point2D(i, i);
var otherCell = map.GetTile(otherCellCoords);

if (otherCell != null)
{
var tlCoords = CellTopLeftPointFromCellCoords(otherCellCoords, map);
var centerCoords = CellCenterPointFromCellCoords_3D(otherCellCoords, map);

// Take isometric perspective into account
centerCoords = new Point2D(centerCoords.X / 2, centerCoords.Y);
var twpx = new Point2D(pixelCoords.X / 2, pixelCoords.Y);

float distance = Vector2.Distance(centerCoords.ToXNAVector(), twpx.ToXNAVector());
float distance = Vector2.Distance(centerCoords.ToXNAVector(), worldCoordsNonIsometric);
if (distance <= nearestDistance)
{
nearestDistance = distance;
nearestCenterCoords = otherCellCoords;
bool acceptCell = true;

if (!seethrough)
{
// If seethrough is disabled and the "currently nearest" cell is below the evaluated cell in 2D coords,
// only accept the evaluated cell as nearest if it is significantly closer than the nearest cell.
if (otherCellCoords.X + otherCellCoords.Y < nearestCenterCoords.X + nearestCenterCoords.Y)
{
if (nearestDistance - distance <= threshold)
{
acceptCell = false;
}
}
}

if (acceptCell)
{
nearestDistance = distance;
nearestCenterCoords = otherCellCoords;
}
}

// If seethrough is disabled, we need to additionally check if the evaluated cell could be the closest cell at
// any potential height level, if it'd be below the current nearest cell in 2D mode
if (!seethrough && otherCellCoords.X + otherCellCoords.Y > nearestCenterCoords.X + nearestCenterCoords.Y)
{
for (int h = 0; h < otherCell.Level; h++)
{
centerCoords = CellCenterPointFromCellCoords(otherCellCoords, map);
centerCoords = new Point2D(centerCoords.X / 2, centerCoords.Y - Constants.CellHeight * h);

distance = Vector2.Distance(centerCoords.ToXNAVector(), worldCoordsNonIsometric);

if (distance <= nearestDistance)
{
nearestDistance = distance;
nearestCenterCoords = otherCellCoords;
}
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/TSMapEditor/Rendering/MapView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1285,7 +1285,7 @@ public override void Update(GameTime gameTime)
Point2D cursorMapPoint = GetCursorMapPoint();
Point2D tileCoords = EditorState.Is2DMode ?
CellMath.CellCoordsFromPixelCoords_2D(cursorMapPoint, Map) :
CellMath.CellCoordsFromPixelCoords(cursorMapPoint, Map);
CellMath.CellCoordsFromPixelCoords(cursorMapPoint, Map, CursorAction == null || CursorAction.SeeThrough);

var tile = Map.GetTile(tileCoords.X, tileCoords.Y);

Expand Down
7 changes: 7 additions & 0 deletions src/TSMapEditor/UI/CursorAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ public CursorAction(ICursorActionTarget cursorActionTarget)
/// </summary>
public virtual bool DrawCellCursor => false;

/// <summary>
/// Override in derived classes to disable "see-through" cell cursor behaviour.
/// "See-through" behaviour allows the cursor action to reach cells behind "walls"
/// in the game world, such as cliffs.
/// </summary>
public virtual bool SeeThrough => true;

public abstract string GetName();

protected Map Map => CursorActionTarget.Map;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ public FlattenGroundCursorAction(ICursorActionTarget cursorActionTarget) : base(

public override bool DrawCellCursor => true;

public override bool SeeThrough => false;

public override void LeftDown(Point2D cellCoords)
{
var cell = Map.GetTile(cellCoords);
Expand Down

0 comments on commit cdcc6cf

Please sign in to comment.