Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make tokens more closely follow their leader #4817

Merged
merged 10 commits into from
Jun 4, 2024
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
Loading