v10 compat: Split measure function into several subfunctions as suggested by Foundry v10
This commit is contained in:
+2
-206
@@ -1,25 +1,8 @@
|
|||||||
import {highlightMeasurementTerrainRuler, measureDistances} from "./compatibility.js";
|
import {getGridPositionFromPixels} from "./foundry_fixes.js";
|
||||||
import {
|
|
||||||
getGridPositionFromPixels,
|
|
||||||
getGridPositionFromPixelsObj,
|
|
||||||
getPixelsFromGridPositionObj,
|
|
||||||
} from "./foundry_fixes.js";
|
|
||||||
import {Line} from "./geometry.js";
|
|
||||||
import {disableSnap, moveWithoutAnimation} from "./keybindings.js";
|
import {disableSnap, moveWithoutAnimation} from "./keybindings.js";
|
||||||
import {trackRays} from "./movement_tracking.js";
|
import {trackRays} from "./movement_tracking.js";
|
||||||
import {findPath, isPathfindingEnabled} from "./pathfinding.js";
|
|
||||||
import {settingsKey} from "./settings.js";
|
|
||||||
import {recalculate} from "./socket.js";
|
import {recalculate} from "./socket.js";
|
||||||
import {
|
import {getSnapPointForToken, highlightTokenShape, sum} from "./util.js";
|
||||||
applyTokenSizeOffset,
|
|
||||||
enumeratedZip,
|
|
||||||
getSnapPointForEntity,
|
|
||||||
getSnapPointForToken,
|
|
||||||
getSnapPointForTokenObj,
|
|
||||||
getTokenShape,
|
|
||||||
highlightTokenShape,
|
|
||||||
sum,
|
|
||||||
} from "./util.js";
|
|
||||||
|
|
||||||
// This is a modified version of Ruler.moveToken from foundry 0.7.9
|
// This is a modified version of Ruler.moveToken from foundry 0.7.9
|
||||||
export async function moveEntities(draggedEntity, selectedEntities) {
|
export async function moveEntities(draggedEntity, selectedEntities) {
|
||||||
@@ -195,193 +178,6 @@ export function cancelScheduledMeasurement() {
|
|||||||
this.deferredMeasurementResolve?.();
|
this.deferredMeasurementResolve?.();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a modified version of Ruler.measure form foundry 0.7.9
|
|
||||||
export function measure(destination, options = {}) {
|
|
||||||
const isToken = this.draggedEntity instanceof Token;
|
|
||||||
if (isToken && !this.draggedEntity.isVisible) return [];
|
|
||||||
|
|
||||||
options.snap = options.snap ?? !disableSnap;
|
|
||||||
|
|
||||||
if (options.snap) {
|
|
||||||
destination = getSnapPointForEntity(destination.x, destination.y, this.draggedEntity);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.dragRulerRemovePathfindingWaypoints();
|
|
||||||
|
|
||||||
if (isToken && isPathfindingEnabled.call(this)) {
|
|
||||||
const from = getGridPositionFromPixelsObj(this.waypoints[this.waypoints.length - 1]);
|
|
||||||
const to = getGridPositionFromPixelsObj(destination);
|
|
||||||
let path = findPath(from, to, this.draggedEntity, this.waypoints);
|
|
||||||
if (path) path.shift();
|
|
||||||
if (path && path.length > 0) {
|
|
||||||
path = path.map(point =>
|
|
||||||
getSnapPointForTokenObj(getPixelsFromGridPositionObj(point), this.draggedEntity),
|
|
||||||
);
|
|
||||||
|
|
||||||
// If the token is snapped to the grid, the first point of the path is already handled by the ruler
|
|
||||||
if (
|
|
||||||
path[0].x === this.waypoints[this.waypoints.length - 1].x &&
|
|
||||||
path[0].y === this.waypoints[this.waypoints.length - 1].y
|
|
||||||
)
|
|
||||||
path = path.slice(1);
|
|
||||||
|
|
||||||
// If snapping is enabled, the last point of the path is already handled by the ruler
|
|
||||||
if (options.snap) path = path.slice(0, path.length - 1);
|
|
||||||
|
|
||||||
for (const point of path) {
|
|
||||||
point.isPathfinding = true;
|
|
||||||
this.labels.addChild(new PreciseText("", CONFIG.canvasTextStyle));
|
|
||||||
}
|
|
||||||
this.waypoints = this.waypoints.concat(path);
|
|
||||||
} else {
|
|
||||||
// Don't show a path if the pathfinding yields no result to show the user that the destination is unreachable
|
|
||||||
destination = this.waypoints[this.waypoints.length - 1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.gridSpaces === undefined) {
|
|
||||||
options.gridSpaces = canvas.grid.type !== CONST.GRID_TYPES.GRIDLESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (canvas.grid.diagonalRule === "EUCL") {
|
|
||||||
options.gridSpaces = false;
|
|
||||||
options.ignoreGrid = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.ignoreGrid === undefined) {
|
|
||||||
options.ignoreGrid = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
options.enableTerrainRuler = isToken && game.modules.get("terrain-ruler")?.active;
|
|
||||||
|
|
||||||
const waypoints = this.waypoints.concat([destination]);
|
|
||||||
// Move the waypoints to the center of the grid if a size is used that measures from edge to edge
|
|
||||||
const centeredWaypoints = isToken
|
|
||||||
? applyTokenSizeOffset(waypoints, this.draggedEntity)
|
|
||||||
: duplicate(waypoints);
|
|
||||||
// Foundries native ruler requires the waypoints to sit in the dead center of the square to work properly
|
|
||||||
if (!options.enableTerrainRuler && !options.ignoreGrid)
|
|
||||||
centeredWaypoints.forEach(w => ([w.x, w.y] = canvas.grid.getCenter(w.x, w.y)));
|
|
||||||
|
|
||||||
const r = this.ruler;
|
|
||||||
this.destination = destination;
|
|
||||||
|
|
||||||
// Iterate over waypoints and construct segment rays
|
|
||||||
const segments = [];
|
|
||||||
const centeredSegments = [];
|
|
||||||
for (let [i, dest] of waypoints.slice(1).entries()) {
|
|
||||||
const centeredDest = centeredWaypoints[i + 1];
|
|
||||||
const origin = waypoints[i];
|
|
||||||
const centeredOrigin = centeredWaypoints[i];
|
|
||||||
const label = this.labels.children[i];
|
|
||||||
const ray = new Ray(origin, dest);
|
|
||||||
const centeredRay = new Ray(centeredOrigin, centeredDest);
|
|
||||||
ray.isPrevious = Boolean(origin.isPrevious);
|
|
||||||
centeredRay.isPrevious = ray.isPrevious;
|
|
||||||
ray.dragRulerVisitedSpaces = origin.dragRulerVisitedSpaces;
|
|
||||||
centeredRay.dragRulerVisitedSpaces = ray.dragRulerVisitedSpaces;
|
|
||||||
ray.dragRulerFinalState = origin.dragRulerFinalState;
|
|
||||||
centeredRay.dragRulerFinalState = ray.dragRulerFinalState;
|
|
||||||
if (ray.distance < 10) {
|
|
||||||
if (label) label.visible = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
segments.push({ray, label});
|
|
||||||
centeredSegments.push({ray: centeredRay, label});
|
|
||||||
}
|
|
||||||
|
|
||||||
const shape = isToken ? getTokenShape(this.draggedEntity) : null;
|
|
||||||
|
|
||||||
// Compute measured distance
|
|
||||||
const distances = measureDistances(centeredSegments, this.draggedEntity, shape, options);
|
|
||||||
|
|
||||||
let totalDistance = 0;
|
|
||||||
for (let [i, d] of distances.entries()) {
|
|
||||||
let s = centeredSegments[i];
|
|
||||||
s.startDistance = totalDistance;
|
|
||||||
totalDistance += d;
|
|
||||||
s.last = i === centeredSegments.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();
|
|
||||||
let rulerColor;
|
|
||||||
if (!options.gridSpaces || canvas.grid.type === CONST.GRID_TYPES.GRIDLESS)
|
|
||||||
rulerColor = this.dragRulerGetColorForDistance(totalDistance);
|
|
||||||
else rulerColor = this.color;
|
|
||||||
for (const [i, s, cs] of enumeratedZip(
|
|
||||||
[...segments].reverse(),
|
|
||||||
[...centeredSegments].reverse(),
|
|
||||||
)) {
|
|
||||||
const {label, text, last} = cs;
|
|
||||||
|
|
||||||
// Draw line segment
|
|
||||||
const opacityMultiplier = s.ray.isPrevious ? 0.33 : 1;
|
|
||||||
r.lineStyle(6, 0x000000, 0.5 * opacityMultiplier)
|
|
||||||
.moveTo(s.ray.A.x, s.ray.A.y)
|
|
||||||
.lineTo(s.ray.B.x, s.ray.B.y)
|
|
||||||
.lineStyle(4, rulerColor, 0.25 * opacityMultiplier)
|
|
||||||
.moveTo(s.ray.A.x, s.ray.A.y)
|
|
||||||
.lineTo(s.ray.B.x, s.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 = {x: s.ray.x0, y: s.ray.y0};
|
|
||||||
labelPosition.x -= label.width / 2;
|
|
||||||
labelPosition.y -= label.height / 2;
|
|
||||||
const rayLine = Line.fromPoints(s.ray.A, s.ray.B);
|
|
||||||
const rayLabelXHitY = rayLine.calcY(labelPosition.x);
|
|
||||||
let innerDistance;
|
|
||||||
// If ray hits top or bottom side of label
|
|
||||||
if (
|
|
||||||
rayLine.isVertical ||
|
|
||||||
rayLabelXHitY < labelPosition.y ||
|
|
||||||
rayLabelXHitY > labelPosition.y + label.height
|
|
||||||
)
|
|
||||||
innerDistance = Math.abs(label.height / 2 / Math.sin(s.ray.angle));
|
|
||||||
// If ray hits left or right side of label
|
|
||||||
else innerDistance = Math.abs(label.width / 2 / Math.cos(s.ray.angle));
|
|
||||||
labelPosition = s.ray.project((s.ray.distance + 50 + innerDistance) / s.ray.distance);
|
|
||||||
labelPosition.x -= label.width / 2;
|
|
||||||
labelPosition.y -= label.height / 2;
|
|
||||||
label.position.set(labelPosition.x, labelPosition.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Highlight grid positions
|
|
||||||
if (isToken && canvas.grid.type !== CONST.GRID_TYPES.GRIDLESS && options.gridSpaces) {
|
|
||||||
if (options.enableTerrainRuler) {
|
|
||||||
highlightMeasurementTerrainRuler.call(
|
|
||||||
this,
|
|
||||||
cs.ray,
|
|
||||||
cs.startDistance,
|
|
||||||
shape,
|
|
||||||
opacityMultiplier,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
const previousSegments = centeredSegments.slice(0, segments.length - 1 - i);
|
|
||||||
highlightMeasurementNative.call(this, cs.ray, previousSegments, shape, opacityMultiplier);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw endpoints
|
|
||||||
for (let p of waypoints) {
|
|
||||||
r.lineStyle(2, 0x000000, 0.5).beginFill(rulerColor, 0.25).drawCircle(p.x, p.y, 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the measured segments
|
|
||||||
return segments;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function highlightMeasurementNative(
|
export function highlightMeasurementNative(
|
||||||
ray,
|
ray,
|
||||||
previousSegments,
|
previousSegments,
|
||||||
|
|||||||
+231
-8
@@ -3,11 +3,16 @@ import {
|
|||||||
getColorForDistanceAndToken,
|
getColorForDistanceAndToken,
|
||||||
getRangesFromSpeedProvider,
|
getRangesFromSpeedProvider,
|
||||||
} from "./api.js";
|
} from "./api.js";
|
||||||
import {getHexSizeSupportTokenGridCenter} from "./compatibility.js";
|
import {
|
||||||
import {cancelScheduledMeasurement, measure} from "./foundry_imports.js";
|
getHexSizeSupportTokenGridCenter,
|
||||||
|
highlightMeasurementTerrainRuler,
|
||||||
|
measureDistances,
|
||||||
|
} from "./compatibility.js";
|
||||||
|
import {cancelScheduledMeasurement, highlightMeasurementNative} from "./foundry_imports.js";
|
||||||
|
import {disableSnap} from "./keybindings.js";
|
||||||
import {getMovementHistory} from "./movement_tracking.js";
|
import {getMovementHistory} from "./movement_tracking.js";
|
||||||
import {settingsKey} from "./settings.js";
|
import {settingsKey} from "./settings.js";
|
||||||
import {getSnapPointForEntity} from "./util.js";
|
import {applyTokenSizeOffset, getSnapPointForEntity, getTokenShape} from "./util.js";
|
||||||
|
|
||||||
export function extendRuler() {
|
export function extendRuler() {
|
||||||
class DragRulerRuler extends CONFIG.Canvas.rulerClass {
|
class DragRulerRuler extends CONFIG.Canvas.rulerClass {
|
||||||
@@ -67,13 +72,231 @@ export function extendRuler() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
measure(destination, options = {}) {
|
measure(destination, options = {}) {
|
||||||
if (this.isDragRuler) {
|
if (!this.isDragRuler) {
|
||||||
// If this is the ruler of a remote user take the waypoints as they were transmitted and don't apply any additional snapping to them
|
|
||||||
if (this.user !== game.user) options.snap = false;
|
|
||||||
return measure.call(this, destination, options);
|
|
||||||
} else {
|
|
||||||
return super.measure(destination, options);
|
return super.measure(destination, options);
|
||||||
}
|
}
|
||||||
|
if (options.gridSpaces === undefined) {
|
||||||
|
options.gridSpaces = canvas.grid.type !== CONST.GRID_TYPES.GRIDLESS;
|
||||||
|
}
|
||||||
|
this.dragRulerGridSpaces = options.gridSpaces;
|
||||||
|
const isToken = this.draggedEntity instanceof Token;
|
||||||
|
if (isToken && !this.draggedEntity.isVisible) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
if (canvas.grid.diagonalRule === "EUCL") {
|
||||||
|
options.gridSpaces = false;
|
||||||
|
options.ignoreGrid = true;
|
||||||
|
}
|
||||||
|
if (options.ignoreGrid === undefined) {
|
||||||
|
options.ignoreGrid = false;
|
||||||
|
}
|
||||||
|
this.dragRulerIgnoreGrid = options.ignoreGrid;
|
||||||
|
// If this is the ruler of a remote user take the waypoints as they were transmitted and don't apply any additional snapping to them
|
||||||
|
if (this.user !== game.user) {
|
||||||
|
options.snap = false;
|
||||||
|
}
|
||||||
|
this.dragRulerSnap = options.snap ?? !disableSnap;
|
||||||
|
this.dragRulerEnableTerrainRuler = isToken && window.terrainRuler;
|
||||||
|
|
||||||
|
// Compute the measurement destination, segments, and distance
|
||||||
|
const d = this._getMeasurementDestination(destination);
|
||||||
|
if (d.x === this.destination.x && d.y === this.destination.y) return;
|
||||||
|
this.destination = d;
|
||||||
|
this.segments = this._getMeasurementSegments();
|
||||||
|
this._computeDistance(options.gridSpaces);
|
||||||
|
|
||||||
|
// Draw the ruler graphic
|
||||||
|
this.ruler.clear();
|
||||||
|
this._drawMeasuredPath();
|
||||||
|
|
||||||
|
// Draw grid highlight
|
||||||
|
this.highlightLayer.clear();
|
||||||
|
if (isToken && canvas.grid.type !== CONST.GRID_TYPES.GRIDLESS && this.dragRulerGridSpaces) {
|
||||||
|
const shape = getTokenShape(this.draggedEntity);
|
||||||
|
if (!this.dragRulerEnableTerrainRuler) {
|
||||||
|
for (const [i, segment] of [...this.segments].reverse().entries()) {
|
||||||
|
const opacityMultiplier = segment.ray.isPrevious ? 0.33 : 1;
|
||||||
|
const previousSegments = this.segments.slice(0, this.segments.length - 1 - i);
|
||||||
|
highlightMeasurementNative.call(
|
||||||
|
this,
|
||||||
|
segment.ray,
|
||||||
|
previousSegments,
|
||||||
|
shape,
|
||||||
|
opacityMultiplier,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (const segment of [...this.dragRulerUnsnappedSegments].reverse()) {
|
||||||
|
const opacityMultiplier = segment.ray.isPrevious ? 0.33 : 1;
|
||||||
|
highlightMeasurementTerrainRuler.call(
|
||||||
|
this,
|
||||||
|
segment.ray,
|
||||||
|
segment.startDistance,
|
||||||
|
shape,
|
||||||
|
opacityMultiplier,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.segments;
|
||||||
|
}
|
||||||
|
|
||||||
|
_getMeasurementDestination(destination) {
|
||||||
|
if (this.isDragRuler) {
|
||||||
|
if (this.dragRulerSnap) {
|
||||||
|
return getSnapPointForEntity(destination.x, destination.y, this.draggedEntity);
|
||||||
|
} else {
|
||||||
|
return destination;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return super._getMeasurementDestination(destination);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_getMeasurementSegments() {
|
||||||
|
// TODO Recalculate pathfinding, if necessary
|
||||||
|
if (this.isDragRuler) {
|
||||||
|
const unsnappedWaypoints = this.waypoints.concat([this.destination]);
|
||||||
|
const waypoints =
|
||||||
|
this.draggedEntity instanceof Token
|
||||||
|
? applyTokenSizeOffset(unsnappedWaypoints, this.draggedEntity)
|
||||||
|
: duplicate(unsnappedWaypoints);
|
||||||
|
const unsnappedSegments = [];
|
||||||
|
const segments = [];
|
||||||
|
for (const [i, p1] of waypoints.entries()) {
|
||||||
|
if (i === 0) continue;
|
||||||
|
const unsnappedP1 = unsnappedWaypoints[i];
|
||||||
|
const p0 = waypoints[i - 1];
|
||||||
|
const unsnappedP0 = unsnappedWaypoints[i - 1];
|
||||||
|
const label = this.labels.children[i - 1];
|
||||||
|
const ray = new Ray(p0, p1);
|
||||||
|
const unsnappedRay = new Ray(unsnappedP0, unsnappedP1);
|
||||||
|
ray.isPrevious = Boolean(unsnappedP0.isPrevious);
|
||||||
|
unsnappedRay.isPrevious = ray.isPrevious;
|
||||||
|
ray.dragRulerVisitedSpaces = unsnappedP0.dragRulerVisitedSpaces;
|
||||||
|
unsnappedRay.dragRulerVisitedSpaces = ray.dragRulerVisitedSpaces;
|
||||||
|
ray.dragRulerFinalState = unsnappedP0.dragRulerFinalState;
|
||||||
|
unsnappedRay.dragRulerFinalState = ray.dragRulerFinalState;
|
||||||
|
if (ray.distance < 10) {
|
||||||
|
if (label) label.visible = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
segments.push({ray, label});
|
||||||
|
unsnappedSegments.push({ray: unsnappedRay, label});
|
||||||
|
}
|
||||||
|
this.dragRulerUnsnappedSegments = unsnappedSegments;
|
||||||
|
return segments;
|
||||||
|
} else {
|
||||||
|
return super._getMeasurementSegments();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_computeDistance(gridSpaces) {
|
||||||
|
if (!this.isDragRuler) {
|
||||||
|
return super._computeDistance(gridSpaces);
|
||||||
|
}
|
||||||
|
if (!this.dragRulerEnableTerrainRuler) {
|
||||||
|
if (!this.dragRulerIgnoreGrid) {
|
||||||
|
gridSpaces = true;
|
||||||
|
}
|
||||||
|
super._computeDistance(gridSpaces);
|
||||||
|
} else {
|
||||||
|
const shape = this.draggedEntity ? getTokenShape(this.draggedEntity) : null;
|
||||||
|
const options = {
|
||||||
|
ignoreGrid: this.dragRulerIgnoreGrid,
|
||||||
|
gridSpaces,
|
||||||
|
enableTerrainRuler: this.dragRulerEnableTerrainRuler,
|
||||||
|
};
|
||||||
|
const distances = measureDistances(this.segments, this.draggedEntity, shape, options);
|
||||||
|
for (const [i, d] of distances.entries()) {
|
||||||
|
totalDistance += d;
|
||||||
|
let s = this.segements[i];
|
||||||
|
s.last = i === this.segements.length - 1;
|
||||||
|
s.distance = d;
|
||||||
|
s.text = this._getSegmentLabel(s, totalDistance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*if (!this.dragRulerEnableTerrainRuler) {
|
||||||
|
if (!this.dragRulerIgnoreGrid) {
|
||||||
|
gridSpaces = true;
|
||||||
|
}
|
||||||
|
super._computeDistance(gridSpaces);
|
||||||
|
} else {
|
||||||
|
const unsnappedSegments = this.dragRulerUnsnappedSegments;
|
||||||
|
const firstNewSegmentIndex = unsnappedSegments.findIndex(
|
||||||
|
segment => !segment.ray.dragRulerVisitedSpaces,
|
||||||
|
);
|
||||||
|
const previousSegments = unsnappedSegments.slice(0, firstNewSegmentIndex);
|
||||||
|
const newSegments = unsnappedSegments.slice(firstNewSegmentIndex);
|
||||||
|
const distances = previousSegments.map(
|
||||||
|
segment =>
|
||||||
|
segment.ray.dragRulerVisitedSpaces[segment.ray.dragRulerVisitedSpaces.length - 1]
|
||||||
|
.distance,
|
||||||
|
);
|
||||||
|
previousSegments.forEach(
|
||||||
|
segment =>
|
||||||
|
(segment.ray.terrainRulerVisitedSpaces = duplicate(segment.ray.dragRulerVisitedSpaces)),
|
||||||
|
);
|
||||||
|
const shape = isToken ? getTokenShape(this.draggedEntity) : null;
|
||||||
|
const options = {};
|
||||||
|
options.costFunction = buildCostFunction(this.draggedEntity, shape);
|
||||||
|
if (previousSegments.length > 0)
|
||||||
|
opts.terrainRulerInitialState =
|
||||||
|
previousSegments[previousSegments.length - 1].ray.dragRulerFinalState;
|
||||||
|
distances = distances.concat(terrainRuler.measureDistances(newSegments, options));
|
||||||
|
for (const [i, d] of distances.entries()) {
|
||||||
|
totalDistance += d;
|
||||||
|
let s = this.segements[i];
|
||||||
|
s.last = i === this.segements.length - 1;
|
||||||
|
s.distance = d;
|
||||||
|
s.text = this._getSegmentLabel(s, totalDistance);
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
for (const [i, segment] of this.segments.entries()) {
|
||||||
|
const unsnappedSegment = this.dragRulerUnsnappedSegments[i];
|
||||||
|
unsnappedSegment.last = segment.last;
|
||||||
|
unsnappedSegment.distance = segment.distance;
|
||||||
|
unsnappedSegment.text = segment.text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_drawMeasuredPath() {
|
||||||
|
if (!this.isDragRuler) {
|
||||||
|
return super._drawMeasuredPath();
|
||||||
|
}
|
||||||
|
let rulerColor = this.color;
|
||||||
|
if (!this.dragRulerGridSpaces || canvas.grid.type === CONST.GRID_TYPES.GRIDLESS) {
|
||||||
|
const totalDistance = this.segments.reduce((total, current) => total + current.distance, 0);
|
||||||
|
rulerColor = this.dragRulerGetColorForDistance(totalDistance);
|
||||||
|
}
|
||||||
|
const r = this.ruler.beginFill(rulerColor, 0.25);
|
||||||
|
for (const segment of this.dragRulerUnsnappedSegments) {
|
||||||
|
const opacityMultiplier = segment.ray.isPrevious ? 0.33 : 1;
|
||||||
|
const {ray, distance, label, text, last} = segment;
|
||||||
|
if (distance === 0) continue;
|
||||||
|
|
||||||
|
// Draw Line
|
||||||
|
r.moveTo(ray.A.x, ray.A.y)
|
||||||
|
.lineStyle(6, 0x000000, 0.5 * opacityMultiplier)
|
||||||
|
.lineTo(ray.B.x, ray.B.y)
|
||||||
|
.lineStyle(4, rulerColor, 0.25 * opacityMultiplier)
|
||||||
|
.moveTo(ray.A.x, ray.A.y)
|
||||||
|
.lineTo(ray.B.x, ray.B.y);
|
||||||
|
|
||||||
|
// Draw Waypoints
|
||||||
|
r.lineStyle(2, 0x000000, 0.5).drawCircle(ray.A.x, ray.A.y, 8);
|
||||||
|
if (last) r.drawCircle(ray.B.x, ray.B.y, 8);
|
||||||
|
|
||||||
|
// Draw Label
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r.endFill();
|
||||||
}
|
}
|
||||||
|
|
||||||
_endMeasurement() {
|
_endMeasurement() {
|
||||||
|
|||||||
Reference in New Issue
Block a user