Skip to content

Commit

Permalink
Merge pull request #4817 from kwvanderlinde/bugfix/4813-follower-paths
Browse files Browse the repository at this point in the history
Make tokens more closely follow their leader
  • Loading branch information
cwisniew authored Jun 4, 2024
2 parents 7e376ea + 9be8dce commit 58127f6
Show file tree
Hide file tree
Showing 13 changed files with 918 additions and 457 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -485,39 +486,27 @@ private String getMovement(
Zone zone = zr.getZone();
Grid grid = zone.getGrid();

Path<ZonePoint> gridlessPath;
/*
* Lee: causes an NPE when used on a newly dropped token. While a true solution would probably be to create a "path" based on the token's coords when it is dropped on the map, the easy out
* here would be to just return a "0".
*
* Final Edit: attempting to create a default path for new drops had undesirable effects. Therefore, let's opt for the easy fix
*/
int x = 0, y = 0;

try {
x = source.getLastPath().getCellPath().get(0).x;
y = source.getLastPath().getCellPath().get(0).y;
} catch (NullPointerException e) {
List<? extends AbstractPoint> cellPath =
source.getLastPath() == null ? Collections.emptyList() : source.getLastPath().getCellPath();
if (cellPath.isEmpty()) {
return "0";
}

if (useTerrainModifiers && !returnFractionOnly) {
if (source.getLastPath().getLastWaypoint() instanceof CellPoint) {
CellPoint cp = (CellPoint) source.getLastPath().getLastWaypoint();
if (cellPath.getLast() instanceof CellPoint cp) {
double trueDistance = cp.getDistanceTraveled(zone);

return new BigDecimal(trueDistance).stripTrailingZeros().toPlainString();
}
}

if (source.isSnapToGrid() && grid.getCapabilities().isSnapToGridSupported()) {
if (zone.getGrid().getCapabilities().isPathingSupported()) {
var firstPoint = cellPath.getFirst();
List<CellPoint> cplist = new ArrayList<CellPoint>();
walker = grid.createZoneWalker();
walker.replaceLastWaypoint(new CellPoint(x, y));
for (AbstractPoint point : source.getLastPath().getCellPath()) {
walker.replaceLastWaypoint(new CellPoint(firstPoint.x, firstPoint.y));
for (AbstractPoint point : cellPath) {
CellPoint tokenPoint = new CellPoint(point.x, point.y);
// walker.setWaypoints(tokenPoint);
walker.replaceLastWaypoint(tokenPoint);
cplist.add(tokenPoint);
}
Expand All @@ -534,21 +523,18 @@ private String getMovement(
// return Integer.toString(walker.getDistance());
}
} else {
gridlessPath = new Path<ZonePoint>();
for (AbstractPoint point : source.getLastPath().getCellPath()) {
gridlessPath.addPathCell(new ZonePoint(point.x, point.y));
}
double c = 0;
ZonePoint lastPoint = null;
for (ZonePoint zp : gridlessPath.getCellPath()) {
// Should be a ZonePoint, but the calculation just doesn't care.
AbstractPoint lastPoint = null;
for (var point : cellPath) {
if (lastPoint == null) {
lastPoint = zp;
lastPoint = point;
continue;
}
int a = lastPoint.x - zp.x;
int b = lastPoint.y - zp.y;
int a = lastPoint.x - point.x;
int b = lastPoint.y - point.y;
c += Math.hypot(a, b);
lastPoint = zp;
lastPoint = point;
}
c /= zone.getGrid().getSize(); // Number of "cells"
c *= zone.getUnitsPerCell(); // "actual" distance traveled
Expand Down
80 changes: 35 additions & 45 deletions src/main/java/net/rptools/maptool/client/tool/MeasureTool.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
*/
package net.rptools.maptool.client.tool;

import com.google.common.collect.Iterables;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Graphics2D;
Expand All @@ -22,7 +23,9 @@
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.geom.Path2D;
import java.text.NumberFormat;
import java.util.List;
import java.util.Map;
import javafx.application.Platform;
import javafx.scene.ImageCursor;
Expand All @@ -49,6 +52,8 @@ public class MeasureTool extends DefaultTool implements ZoneOverlay {

private ZoneWalker walker;
private Path<ZonePoint> gridlessPath;
private ZonePoint currentGridlessPoint;

private static Cursor measureCursor;
private static javafx.scene.Cursor measureCursorFX;

Expand Down Expand Up @@ -93,57 +98,47 @@ public String getInstructions() {
}

public void paintOverlay(ZoneRenderer renderer, Graphics2D g) {
if (walker == null && gridlessPath == null) {
return;
}
if (walker != null) {
renderer.renderPath(g, walker.getPath(), renderer.getZone().getGrid().getDefaultFootprint());
ScreenPoint sp = walker.getLastPoint().convertToScreen(renderer);

int y = (int) sp.y - 10;
int x = (int) sp.x + (int) (renderer.getScaledGridSize() / 2);
GraphicsUtil.drawBoxedString(g, Double.toString(walker.getDistance()), x, y);
} else {
Object oldAA = SwingUtil.useAntiAliasing(g);
g.setColor(Color.black);
ScreenPoint lastPoint = null;
for (ZonePoint zp : gridlessPath.getCellPath()) {
if (lastPoint == null) {
lastPoint = ScreenPoint.fromZonePoint(renderer, zp);
continue;
}
ScreenPoint nextPoint = ScreenPoint.fromZonePoint(renderer, zp.x, zp.y);
g.drawLine((int) lastPoint.x, (int) lastPoint.y, (int) nextPoint.x, (int) nextPoint.y);
lastPoint = nextPoint;
}

} else if (gridlessPath != null) {
// distance
double c = 0;
var path2D = new Path2D.Double();
ZonePoint lastZP = null;
for (ZonePoint zp : gridlessPath.getCellPath()) {
for (ZonePoint zp :
Iterables.concat(gridlessPath.getCellPath(), List.of(currentGridlessPoint))) {
var sp = ScreenPoint.fromZonePoint(renderer, zp.x, zp.y);
if (lastZP == null) {
lastZP = zp;
continue;
path2D.moveTo(sp.x, sp.y);
} else {
path2D.lineTo(sp.x, sp.y);
int a = lastZP.x - zp.x;
int b = lastZP.y - zp.y;
c += Math.sqrt(a * a + b * b);
}
int a = lastZP.x - zp.x;
int b = lastZP.y - zp.y;
c += Math.sqrt(a * a + b * b);
lastZP = zp;
}

// int a = lastPoint.x - (set.offsetX + token.getX());
// int b = lastPoint.y - (set.offsetY + token.getY());
//
// c += Math.sqrt(a*a + b*b)/zone.getUnitsPerCell();
assert lastZP != null : "Our non-empty iterable was empty!";

c /= renderer.getZone().getGrid().getSize();
c *= renderer.getZone().getUnitsPerCell();

String distance = NumberFormat.getInstance().format(c);
ScreenPoint sp = ScreenPoint.fromZonePoint(renderer, lastZP.x, lastZP.y);
GraphicsUtil.drawBoxedString(g, distance, (int) sp.x, (int) sp.y - 20);

SwingUtil.restoreAntiAliasing(g, oldAA);
Object oldAA = SwingUtil.useAntiAliasing(g);
try {
g.setColor(Color.black);
g.draw(path2D);

String distance = NumberFormat.getInstance().format(c);
ScreenPoint sp = ScreenPoint.fromZonePoint(renderer, lastZP.x, lastZP.y);
GraphicsUtil.drawBoxedString(g, distance, (int) sp.x, (int) sp.y - 20);
} finally {
SwingUtil.restoreAntiAliasing(g, oldAA);
}
}
}

Expand All @@ -155,9 +150,6 @@ protected void installKeystrokes(Map<KeyStroke, Action> actionMap) {
KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, false),
new AbstractAction() {
public void actionPerformed(ActionEvent e) {
if (walker == null && gridlessPath == null) {
return;
}
// Waypoint
if (walker != null) {
CellPoint cp =
Expand All @@ -166,9 +158,8 @@ public void actionPerformed(ActionEvent e) {
.getGrid()
.convert(new ScreenPoint(mouseX, mouseY).convertToZone(renderer));
walker.toggleWaypoint(cp);
} else {
gridlessPath.addWayPoint(new ScreenPoint(mouseX, mouseY).convertToZone(renderer));
gridlessPath.addPathCell(new ScreenPoint(mouseX, mouseY).convertToZone(renderer));
} else if (gridlessPath != null) {
gridlessPath.appendWaypoint(currentGridlessPoint);
}
}
});
Expand All @@ -186,11 +177,9 @@ public void mousePressed(java.awt.event.MouseEvent e) {
walker = renderer.getZone().getGrid().createZoneWalker();
walker.addWaypoints(cellPoint, cellPoint);
} else {
gridlessPath = new Path<ZonePoint>();
gridlessPath.addPathCell(new ScreenPoint(e.getX(), e.getY()).convertToZone(renderer));

// Add a second one that will be replaced as the mouse moves around the screen
gridlessPath.addPathCell(new ScreenPoint(e.getX(), e.getY()).convertToZone(renderer));
currentGridlessPoint = new ScreenPoint(e.getX(), e.getY()).convertToZone(renderer);
gridlessPath = new Path<>();
gridlessPath.appendWaypoint(currentGridlessPoint);
}
renderer.repaint();
return;
Expand All @@ -205,6 +194,7 @@ public void mouseReleased(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e)) {
walker = null;
gridlessPath = null;
currentGridlessPoint = null;
renderer.repaint();
return;
}
Expand All @@ -224,7 +214,7 @@ public void mouseDragged(MouseEvent e) {
CellPoint cellPoint = renderer.getCellAt(new ScreenPoint(e.getX(), e.getY()));
walker.replaceLastWaypoint(cellPoint);
} else if (gridlessPath != null) {
gridlessPath.replaceLastPoint(new ScreenPoint(e.getX(), e.getY()).convertToZone(renderer));
currentGridlessPoint = new ScreenPoint(e.getX(), e.getY()).convertToZone(renderer);
}
renderer.repaint();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.annotation.Nonnull;
import net.rptools.maptool.client.MapTool;
import net.rptools.maptool.client.ui.zone.RenderPathWorker;
import net.rptools.maptool.client.walker.ZoneWalker;
Expand All @@ -37,7 +38,8 @@ public class SelectionSet {
private ZoneWalker walker;
private final Token token;

Path<ZonePoint> gridlessPath;
private Path<ZonePoint> gridlessPath;
private ZonePoint currentGridlessPoint;

/** Pixel distance (x) from keyToken's origin. */
int offsetX;
Expand Down Expand Up @@ -72,16 +74,20 @@ public SelectionSet(
walker.setWaypoints(tokenPoint, tokenPoint);
}
} else {
gridlessPath = new Path<ZonePoint>();
gridlessPath.addPathCell(new ZonePoint(token.getX(), token.getY()));
gridlessPath = new Path<>();

currentGridlessPoint = new ZonePoint(token.getX(), token.getY());
gridlessPath.appendWaypoint(currentGridlessPoint);
}
}

/**
* @return path computation.
*/
public Path<ZonePoint> getGridlessPath() {
return gridlessPath;
public @Nonnull Path<ZonePoint> getGridlessPath() {
var result = gridlessPath.copy();
result.appendWaypoint(currentGridlessPoint);
return result;
}

public ZoneWalker getWalker() {
Expand Down Expand Up @@ -151,11 +157,8 @@ public void setOffset(int x, int y) {
renderer);
renderPathThreadPool.execute(renderPathTask);
} else {
if (gridlessPath.getCellPath().size() > 1) {
gridlessPath.replaceLastPoint(zp);
} else {
gridlessPath.addPathCell(zp);
}
currentGridlessPoint.x = zp.x;
currentGridlessPoint.y = zp.y;
}
}

Expand All @@ -168,8 +171,7 @@ public void toggleWaypoint(ZonePoint location) {
if (walker != null && token.isSnapToGrid() && renderer.getZone().getGrid() != null) {
walker.toggleWaypoint(renderer.getZone().getGrid().convert(location));
} else {
gridlessPath.addWayPoint(location);
gridlessPath.addPathCell(location);
gridlessPath.appendWaypoint(location);
}
}

Expand All @@ -193,7 +195,8 @@ public ZonePoint getLastWaypoint() {

zp = renderer.getZone().getGrid().convert(cp);
} else {
zp = gridlessPath.getLastJunctionPoint();
// Gridless path will never be empty if set.
zp = gridlessPath.getWayPointList().getLast();
}
return zp;
}
Expand Down
Loading

0 comments on commit 58127f6

Please sign in to comment.