diff --git a/src/foundry_imports.js b/src/foundry_imports.js index fc0c6f3..422c0f4 100644 --- a/src/foundry_imports.js +++ b/src/foundry_imports.js @@ -95,3 +95,72 @@ export function onMouseMove(event) { this._state = Ruler.STATES.MEASURING; } } + +// This is a modified version of Ruler.measure form foundry 0.7.9 +export function measure(destination, {gridSpaces=true} = {}) { + if (this.isDragRuler && !this.draggedToken.isVisible) + return [] + destination = new PIXI.Point(...canvas.grid.getCenter(destination.x, destination.y)); + const waypoints = this.waypoints.concat([destination]); + const r = this.ruler; + this.destination = destination; + + // Iterate over waypoints and construct segment rays + const segments = []; + for (let [i, dest] of waypoints.slice(1).entries()) { + const origin = waypoints[i]; + const label = this.labels.children[i]; + const ray = new Ray(origin, dest); + if (ray.distance < 10) { + if (label) label.visible = false; + continue; + } + segments.push({ ray, label }); + } + + // Compute measured distance + const distances = canvas.grid.measureDistances(segments, { gridSpaces }); + let totalDistance = 0; + for (let [i, d] of distances.entries()) { + let s = segments[i]; + s.startDistance = totalDistance + totalDistance += d; + s.last = i === (segments.length - 1); + s.distance = d; + s.text = this._getSegmentLabel(d, totalDistance, s.last); + } + + // Clear the grid highlight layer + const hlt = canvas.grid.highlightLayers[this.name] || canvas.grid.addHighlightLayer(this.name); + hlt.clear(); + + // Draw measured path + r.clear(); + for (let s of segments) { + const { ray, label, text, last } = s; + + // Draw line segment + r.lineStyle(6, 0x000000, 0.5).moveTo(ray.A.x, ray.A.y).lineTo(ray.B.x, ray.B.y) + .lineStyle(4, this.color, 0.25).moveTo(ray.A.x, ray.A.y).lineTo(ray.B.x, ray.B.y); + + // Draw the distance label just after the endpoint of the segment + if (label) { + label.text = text; + label.alpha = last ? 1.0 : 0.5; + label.visible = true; + let labelPosition = ray.project((ray.distance + 50) / ray.distance); + label.position.set(labelPosition.x, labelPosition.y); + } + + // Highlight grid positions + this._highlightMeasurement(ray, s.startDistance); + } + + // Draw endpoints + for (let p of waypoints) { + r.lineStyle(2, 0x000000, 0.5).beginFill(this.color, 0.25).drawCircle(p.x, p.y, 8); + } + + // Return the measured segments + return segments; +} diff --git a/src/main.js b/src/main.js index e42c2f1..0e48c92 100644 --- a/src/main.js +++ b/src/main.js @@ -1,14 +1,13 @@ "use strict" import {availableSpeedProviders, currentSpeedProvider, registerModule, registerSystem, setCurrentSpeedProvider} from "./api.js" -import {moveTokens, onMouseMove} from "./foundry_imports.js" +import {measure, moveTokens, onMouseMove} from "./foundry_imports.js" import {registerSettings, settingsKey} from "./settings.js" Hooks.once("init", () => { registerSettings() hookTokenDragHandlers() hookRulerFunctions() - patchRulerMeasure() patchRulerHighlightMeasurement() availableSpeedProviders["native"] = nativeSpeedProvider @@ -89,6 +88,16 @@ function hookRulerFunctions() { } originalUpdate.call(this, data) } + + const originalMeasure = Ruler.prototype.measure + Ruler.prototype.measure = function (destination, options={}) { + if (this.isDragRuler) { + return measure.call(this, destination, options) + } + else { + return originalMeasure.call(this, destination, options) + } + } } function onTokenLeftDragStart(event) { @@ -144,22 +153,6 @@ function strInsertAfter(haystack, needle, strToInsert) { return haystack.slice(0, pos) + strToInsert + haystack.slice(pos) } -// These patches were written with foundry-0.7.9.js as reference -function patchRulerMeasure() { - let code = Ruler.prototype.measure.toString() - // Replace CRLF with LF in case foundry.js has CRLF for some reason - code = code.replace(/\r\n/g, "\n") - // Remove function signature and closing curly bracket (those are on the first and last line) - code = code.slice(code.indexOf("\n"), code.lastIndexOf("\n")) - code = strInsertAfter(code, "for ( let [i, d] of distances.entries() ) {\n", "segments[i].startDistance = totalDistance\n") - code = strInsertAfter(code, "this._highlightMeasurement(ray", ", s.startDistance") - - // Don't show ruler if the measured token is invisible - code = "if (this.isDragRuler && !this.draggedToken.isVisible) return [];" + code - - Ruler.prototype.measure = new Function("destination", "{gridSpaces=true}={}", code) -} - function nativeSpeedProvider(token, playercolor) { const speedAttribute = game.settings.get(settingsKey, "speedAttribute") if (!speedAttribute)