From 384de1a1b59b44100ab91ae272387c226423472d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20V=C3=B6gele?= Date: Tue, 9 Mar 2021 10:02:09 +0100 Subject: [PATCH] Add support for difficult terrain via Terrain Ruler module (resolves #1) --- CHANGELOG.md | 4 ++++ README.md | 7 +++++++ src/compatibility.js | 11 +++++++++++ src/foundry_fixes.js | 21 +++++++++++++++++++++ src/foundry_imports.js | 17 ++++++++++++++--- src/util.js | 5 +++++ 6 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 src/foundry_fixes.js create mode 100644 src/util.js diff --git a/CHANGELOG.md b/CHANGELOG.md index e778466..4bd8b51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## In development +### New features +- If the [Terrain Ruler module](https://foundryvtt.com/packages/terrain-ruler/) is installed and activated, Drag Ruler will now take difficult terrain that was placed with the [TerrainLayer module](https://foundryvtt.com/packages/TerrainLayer/) into account. + ## 1.3.4 ### Module compatibility - Increased compatiblility with other modules (namely Drag Ruler and Terrain Ruler are no longer incompatible) diff --git a/README.md b/README.md index 77e92f1..2673363 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,13 @@ You can add waypoints to the path by pressing spacebar while you drag the token. ![Demonstration of Waypoints](https://raw.githubusercontent.com/manuelVo/foundryvtt-drag-ruler/5177746fbb4edb28b6ba09137247d142af575c47/media/waypoints.webp) +## Difficult Terrain +**To use support for difficult terrain you must install the [Terrain Ruler module](https://foundryvtt.com/packages/terrain-ruler)** + +With the Terrain Ruler module installed, Drag Ruler is able to take difficult terrain that was placed with the [TerrainLayer module](https://foundryvtt.com/packages/TerrainLayer/) into account when measuring distances. + +![Demonstration of Difficult Terrain support](https://raw.githubusercontent.com/manuelVo/foundryvtt-drag-ruler/bb8ac5d1acb9d6374d06f7e9c8e2c2dd61192d56/media/terrain_layer.webp) + ## Why would I want to use this instead of ShowDragDistance? ShowDragDistance isn't maintained anymore. This means that it is at risk to stop working with every foundry update. In fact this process has already begun. As of Foundry Version 0.7.9 ShowDragDistance doesn't work anymore on gridless maps. Drag Ruler on the other hand is fully compatible with the current Foundry release and I'll continue updating it for future foundry releases for the forseeable future. diff --git a/src/compatibility.js b/src/compatibility.js index e61ac85..2a909ab 100644 --- a/src/compatibility.js +++ b/src/compatibility.js @@ -1,3 +1,6 @@ +import {getPixelsFromGridPosition} from "./foundry_fixes.js" +import {getColorForDistance} from "./main.js" + export function getHexSizeSupportTokenGridCenter(token) { const tokenCenterOffset = CONFIG.hexSizeSupport.getCenterOffset(token) const tokenCenter = {x: token.x + tokenCenterOffset.x, y: token.y + tokenCenterOffset.y} @@ -17,3 +20,11 @@ export function getHexSizeSupportTokenGridCenter(token) { } return tokenCenter } + +export function highlightMeasurementTerrainRuler(ray, startDistance) { + for (const space of ray.terrainRulerVisitedSpaces) { + const [x, y] = getPixelsFromGridPosition(space.x, space.y); + const color = getColorForDistance.call(this, startDistance, space.distance) + canvas.grid.highlightPosition(this.name, {x, y, color: color}) + } +} diff --git a/src/foundry_fixes.js b/src/foundry_fixes.js new file mode 100644 index 0000000..56578d2 --- /dev/null +++ b/src/foundry_fixes.js @@ -0,0 +1,21 @@ +// Wrapper to fix a FoundryVTT bug that causes the return values of canvas.grid.grid.getPixelsFromGridPosition to be ordered inconsistently + +// https://gitlab.com/foundrynet/foundryvtt/-/issues/4705 +export function getPixelsFromGridPosition(xGrid, yGrid) { + if (canvas.grid.isHex) { + return canvas.grid.grid.getPixelsFromGridPosition(yGrid, xGrid) + } + const [x, y] = canvas.grid.grid.getPixelsFromGridPosition(xGrid, yGrid) + if (canvas.grid.type === CONST.GRID_TYPES.SQUARE) + return [y, x] + return [x, y] +} + +// Wrapper to fix a FoundryVTT bug that causes the return values of canvas.grid.grid.getPixelsFromGridPosition to be ordered inconsistently +// https://gitlab.com/foundrynet/foundryvtt/-/issues/4705 +export function getGridPositionFromPixels(xPixel, yPixel) { + const [x, y] = canvas.grid.grid.getGridPositionFromPixels(xPixel, yPixel) + if (canvas.grid.type !== CONST.GRID_TYPES.GRIDLESS) + return [y, x] + return [x, y] +} diff --git a/src/foundry_imports.js b/src/foundry_imports.js index 940b176..3da2713 100644 --- a/src/foundry_imports.js +++ b/src/foundry_imports.js @@ -1,4 +1,6 @@ +import {highlightMeasurementTerrainRuler} from "./compatibility.js"; import {getColorForDistance} from "./main.js" +import {zip} from "./util.js" // This is a modified version of Ruler.moveToken from foundry 0.7.9 export async function moveTokens(draggedToken, selectedTokens) { @@ -127,7 +129,13 @@ export function measure(destination, {gridSpaces=true, snap=false} = {}) { } // Compute measured distance - const distances = canvas.grid.measureDistances(centeredSegments, { gridSpaces }); + const terrainRulerAvailable = game.modules.get("terrain-ruler")?.active && canvas.grid.type !== CONST.GRID_TYPES.GRIDLESS + let distances + if (terrainRulerAvailable) + distances = game.terrainRuler.measureDistances(centeredSegments) + else + distances = canvas.grid.measureDistances(centeredSegments, { gridSpaces }); + let totalDistance = 0; for (let [i, d] of distances.entries()) { let s = segments[i]; @@ -149,7 +157,7 @@ export function measure(destination, {gridSpaces=true, snap=false} = {}) { rulerColor = getColorForDistance.call(this, totalDistance) else rulerColor = this.color - for (let s of segments) { + for (const [s, cs] of zip(segments, centeredSegments)) { const { ray, label, text, last } = s; // Draw line segment @@ -166,7 +174,10 @@ export function measure(destination, {gridSpaces=true, snap=false} = {}) { } // Highlight grid positions - highlightMeasurementNative.call(this, ray, s.startDistance); + if (terrainRulerAvailable) + highlightMeasurementTerrainRuler.call(this, cs.ray, s.startDistance) + else + highlightMeasurementNative.call(this, ray, s.startDistance); } // Draw endpoints diff --git a/src/util.js b/src/util.js new file mode 100644 index 0000000..26ab7e4 --- /dev/null +++ b/src/util.js @@ -0,0 +1,5 @@ +export function* zip(it1, it2) { + for (let i = 0;i < Math.min(it1.length, it2.length);i++) { + yield [it1[i], it2[i]] + } +}