Implement measurement template support (resolves #13)
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
**BREAKING** This update is incompatible with previous Terrain Ruler versions. If you're using Terrain Ruler, make sure you update Terrain Ruler to at least version 1.3.0.
|
**BREAKING** This update is incompatible with previous Terrain Ruler versions. If you're using Terrain Ruler, make sure you update Terrain Ruler to at least version 1.3.0.
|
||||||
|
|
||||||
### New features
|
### New features
|
||||||
|
- A ruler will now be shown when dragging measurement templates over the map ([#13](https://github.com/manuelVo/foundryvtt-drag-ruler/issues/13))
|
||||||
- Drag Ruler can now measure difficult terrain on gridless maps (if the Terrain Ruler module is installed and enabled)
|
- Drag Ruler can now measure difficult terrain on gridless maps (if the Terrain Ruler module is installed and enabled)
|
||||||
- Improved the positioning of the labels around the ruler. The labels should now never overlap with the waypoint.
|
- Improved the positioning of the labels around the ruler. The labels should now never overlap with the waypoint.
|
||||||
|
|
||||||
|
|||||||
@@ -15,11 +15,12 @@ export function highlightMeasurementTerrainRuler(ray, startDistance, tokenShape=
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function measureDistances(segments, token, shape, options={}) {
|
export function measureDistances(segments, entity, shape, options={}) {
|
||||||
|
const isToken = entity instanceof Token;
|
||||||
const opts = duplicate(options)
|
const opts = duplicate(options)
|
||||||
if (!opts.gridSpaces)
|
if (!opts.gridSpaces)
|
||||||
opts.gridSpaces = true;
|
opts.gridSpaces = true;
|
||||||
const terrainRulerAvailable = game.modules.get("terrain-ruler")?.active && (!game.modules.get("TerrainLayer")?.active || canvas.grid.type !== CONST.GRID_TYPES.GRIDLESS);
|
const terrainRulerAvailable = isToken && game.modules.get("terrain-ruler")?.active && (!game.modules.get("TerrainLayer")?.active || canvas.grid.type !== CONST.GRID_TYPES.GRIDLESS);
|
||||||
|
|
||||||
if (terrainRulerAvailable) {
|
if (terrainRulerAvailable) {
|
||||||
const firstNewSegmentIndex = segments.findIndex(segment => !segment.ray.dragRulerVisitedSpaces);
|
const firstNewSegmentIndex = segments.findIndex(segment => !segment.ray.dragRulerVisitedSpaces);
|
||||||
@@ -27,7 +28,7 @@ export function measureDistances(segments, token, shape, options={}) {
|
|||||||
const newSegments = segments.slice(firstNewSegmentIndex);
|
const newSegments = segments.slice(firstNewSegmentIndex);
|
||||||
const distances = previousSegments.map(segment => segment.ray.dragRulerVisitedSpaces[segment.ray.dragRulerVisitedSpaces.length - 1].distance);
|
const distances = previousSegments.map(segment => segment.ray.dragRulerVisitedSpaces[segment.ray.dragRulerVisitedSpaces.length - 1].distance);
|
||||||
previousSegments.forEach(segment => segment.ray.terrainRulerVisitedSpaces = duplicate(segment.ray.dragRulerVisitedSpaces));
|
previousSegments.forEach(segment => segment.ray.terrainRulerVisitedSpaces = duplicate(segment.ray.dragRulerVisitedSpaces));
|
||||||
opts.costFunction = (x, y) => getCostFromSpeedProvider(token, getAreaFromPositionAndShape({x, y}, shape), {x, y});
|
opts.costFunction = (x, y) => getCostFromSpeedProvider(entity, getAreaFromPositionAndShape({x, y}, shape), {x, y});
|
||||||
if (previousSegments.length > 0)
|
if (previousSegments.length > 0)
|
||||||
opts.terrainRulerInitialState = previousSegments[previousSegments.length - 1].ray.dragRulerFinalState;
|
opts.terrainRulerInitialState = previousSegments[previousSegments.length - 1].ray.dragRulerFinalState;
|
||||||
return distances.concat(terrainRuler.measureDistances(newSegments, opts));
|
return distances.concat(terrainRuler.measureDistances(newSegments, opts));
|
||||||
|
|||||||
+40
-33
@@ -4,10 +4,10 @@ import {Line} from "./geometry.js";
|
|||||||
import {getColorForDistance} from "./main.js"
|
import {getColorForDistance} from "./main.js"
|
||||||
import {trackRays} from "./movement_tracking.js"
|
import {trackRays} from "./movement_tracking.js"
|
||||||
import {recalculate} from "./socket.js";
|
import {recalculate} from "./socket.js";
|
||||||
import {applyTokenSizeOffset, getSnapPointForToken, getTokenShape, highlightTokenShape, zip} from "./util.js";
|
import {applyTokenSizeOffset, getSnapPointForMeasuredTemplate, getSnapPointForToken, getTokenShape, highlightTokenShape, zip} 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 moveTokens(draggedEntity, selectedTokens) {
|
export async function moveEntities(draggedEntity, selectedEntities) {
|
||||||
let wasPaused = game.paused;
|
let wasPaused = game.paused;
|
||||||
if (wasPaused && !game.user.isGM) {
|
if (wasPaused && !game.user.isGM) {
|
||||||
ui.notifications.warn(game.i18n.localize("GAME.PausedWarning"));
|
ui.notifications.warn(game.i18n.localize("GAME.PausedWarning"));
|
||||||
@@ -19,8 +19,8 @@ export async function moveTokens(draggedEntity, selectedTokens) {
|
|||||||
// Get the movement rays and check collision along each Ray
|
// Get the movement rays and check collision along each Ray
|
||||||
// These rays are center-to-center for the purposes of collision checking
|
// These rays are center-to-center for the purposes of collision checking
|
||||||
const rays = this.constructor.dragRulerGetRaysFromWaypoints(this.waypoints, this.destination);
|
const rays = this.constructor.dragRulerGetRaysFromWaypoints(this.waypoints, this.destination);
|
||||||
if (!game.user.isGM) {
|
if (!game.user.isGM && draggedEntity instanceof Token) {
|
||||||
const hasCollision = selectedTokens.some(token => {
|
const hasCollision = selectedEntities.some(token => {
|
||||||
const offset = calculateTokenOffset(token, draggedEntity);
|
const offset = calculateTokenOffset(token, draggedEntity);
|
||||||
const offsetRays = rays.filter(ray => !ray.isPrevious).map(ray => applyOffsetToRay(ray, offset))
|
const offsetRays = rays.filter(ray => !ray.isPrevious).map(ray => applyOffsetToRay(ray, offset))
|
||||||
return offsetRays.some(r => canvas.walls.checkCollision(r));
|
return offsetRays.some(r => canvas.walls.checkCollision(r));
|
||||||
@@ -35,7 +35,7 @@ export async function moveTokens(draggedEntity, selectedTokens) {
|
|||||||
// Execute the movement path.
|
// Execute the movement path.
|
||||||
// Transform each center-to-center ray into a top-left to top-left ray using the prior token offsets.
|
// Transform each center-to-center ray into a top-left to top-left ray using the prior token offsets.
|
||||||
this._state = Ruler.STATES.MOVING;
|
this._state = Ruler.STATES.MOVING;
|
||||||
await animateTokens.call(this, selectedTokens, draggedEntity, rays, wasPaused);
|
await animateEntities.call(this, selectedEntities, draggedEntity, rays, wasPaused);
|
||||||
|
|
||||||
// Once all animations are complete we can clear the ruler
|
// Once all animations are complete we can clear the ruler
|
||||||
if (this.draggedEntity?.id === draggedEntity.id)
|
if (this.draggedEntity?.id === draggedEntity.id)
|
||||||
@@ -43,51 +43,53 @@ export async function moveTokens(draggedEntity, selectedTokens) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This is a modified version code extracted from Ruler.moveToken from foundry 0.7.9
|
// This is a modified version code extracted from Ruler.moveToken from foundry 0.7.9
|
||||||
async function animateTokens(tokens, draggedEntity, draggedRays, wasPaused) {
|
async function animateEntities(entities, draggedEntity, draggedRays, wasPaused) {
|
||||||
const newRays = draggedRays.filter(r => !r.isPrevious);
|
const newRays = draggedRays.filter(r => !r.isPrevious);
|
||||||
const tokenAnimationData = tokens.map(token => {
|
const entityAnimationData = entities.map(entity => {
|
||||||
const tokenOffset = calculateTokenOffset(token, draggedEntity);
|
const entityOffset = calculateEntityOffset(entity, draggedEntity);
|
||||||
const offsetRays = newRays.map(ray => applyOffsetToRay(ray, tokenOffset));
|
const offsetRays = newRays.map(ray => applyOffsetToRay(ray, entityOffset));
|
||||||
|
|
||||||
// Determine offset relative to the Token top-left.
|
// Determine offset relative to the Token top-left.
|
||||||
// This is important so we can position the token relative to the ruler origin for non-1x1 tokens.
|
// This is important so we can position the token relative to the ruler origin for non-1x1 tokens.
|
||||||
const firstWaypoint = this.waypoints.find(w => !w.isPrevious);
|
const firstWaypoint = this.waypoints.find(w => !w.isPrevious);
|
||||||
const origin = [firstWaypoint.x + tokenOffset.x, firstWaypoint.y + tokenOffset.y];
|
const origin = [firstWaypoint.x + entityOffset.x, firstWaypoint.y + entityOffset.y];
|
||||||
let dx, dy;
|
let dx, dy;
|
||||||
if (canvas.grid.type === CONST.GRID_TYPES.GRIDLESS) {
|
if (canvas.grid.type === CONST.GRID_TYPES.GRIDLESS) {
|
||||||
dx = token.data.x - origin[0];
|
dx = entity.data.x - origin[0];
|
||||||
dy = token.data.y - origin[1];
|
dy = entity.data.y - origin[1];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
dx = token.data.x - origin[0];
|
dx = entity.data.x - origin[0];
|
||||||
dy = token.data.y - origin[1];
|
dy = entity.data.y - origin[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
return {token, rays: offsetRays, dx, dy};
|
return {entity, rays: offsetRays, dx, dy};
|
||||||
});
|
});
|
||||||
|
|
||||||
const animate = !game.keyboard.isDown("Alt");
|
const isToken = draggedEntity instanceof Token;
|
||||||
const startWaypoint = animate ? 0 : tokenAnimationData[0].rays.length - 1;
|
const animate = isToken && !game.keyboard.isDown("Alt");
|
||||||
for (let i = startWaypoint;i < tokenAnimationData[0].rays.length; i++) {
|
const startWaypoint = animate ? 0 : entityAnimationData[0].rays.length - 1;
|
||||||
|
for (let i = startWaypoint;i < entityAnimationData[0].rays.length; i++) {
|
||||||
if (!wasPaused && game.paused) break;
|
if (!wasPaused && game.paused) break;
|
||||||
const tokenPaths = tokenAnimationData.map(({token, rays, dx, dy}) => {
|
const entityPaths = entityAnimationData.map(({entity, rays, dx, dy}) => {
|
||||||
const ray = rays[i];
|
const ray = rays[i];
|
||||||
const dest = [ray.B.x, ray.B.y];
|
const dest = [ray.B.x, ray.B.y];
|
||||||
const path = new Ray({x: token.x, y: token.y}, {x: dest[0] + dx, y: dest[1] + dy});
|
const path = new Ray({x: entity.x, y: entity.y}, {x: dest[0] + dx, y: dest[1] + dy});
|
||||||
return {token, path};
|
return {entity, path};
|
||||||
});
|
});
|
||||||
const updates = tokenPaths.map(({token, path}) => {
|
const updates = entityPaths.map(({entity, path}) => {
|
||||||
return {x: path.B.x, y: path.B.y, _id: token.id};
|
return {x: path.B.x, y: path.B.y, _id: entity.id};
|
||||||
});
|
});
|
||||||
await draggedEntity.scene.updateEmbeddedEntity(draggedEntity.constructor.embeddedName, updates, {animate});
|
await draggedEntity.scene.updateEmbeddedEntity(draggedEntity.constructor.embeddedName, updates, {animate});
|
||||||
if (animate)
|
if (animate)
|
||||||
await Promise.all(tokenPaths.map(({token, path}) => token.animateMovement(path)));
|
await Promise.all(entityPaths.map(({entity, path}) => entity.animateMovement(path)));
|
||||||
}
|
}
|
||||||
trackRays(tokens, tokenAnimationData.map(({rays}) => rays)).then(() => recalculate(tokens));
|
if (isToken)
|
||||||
|
trackRays(entities, entityAnimationData.map(({rays}) => rays)).then(() => recalculate(entities));
|
||||||
}
|
}
|
||||||
|
|
||||||
function calculateTokenOffset(tokenA, tokenB) {
|
function calculateEntityOffset(entityA, entityB) {
|
||||||
return {x: tokenA.data.x - tokenB.data.x, y: tokenA.data.y - tokenB.data.y}
|
return {x: entityA.data.x - entityB.data.x, y: entityA.data.y - entityB.data.y};
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyOffsetToRay(ray, offset) {
|
function applyOffsetToRay(ray, offset) {
|
||||||
@@ -119,17 +121,22 @@ export function onMouseMove(event) {
|
|||||||
|
|
||||||
// This is a modified version of Ruler.measure form foundry 0.7.9
|
// This is a modified version of Ruler.measure form foundry 0.7.9
|
||||||
export function measure(destination, {gridSpaces=true, snap=false} = {}) {
|
export function measure(destination, {gridSpaces=true, snap=false} = {}) {
|
||||||
if (this.isDragRuler && !this.draggedEntity.isVisible)
|
const isToken = this.draggedEntity instanceof Token;
|
||||||
|
if (isToken && !this.draggedEntity.isVisible)
|
||||||
return []
|
return []
|
||||||
|
|
||||||
if (snap)
|
if (snap) {
|
||||||
|
if (isToken)
|
||||||
destination = getSnapPointForToken(destination.x, destination.y, this.draggedEntity);
|
destination = getSnapPointForToken(destination.x, destination.y, this.draggedEntity);
|
||||||
|
else
|
||||||
|
destination = getSnapPointForMeasuredTemplate(destination.x, destination.y);
|
||||||
|
}
|
||||||
|
|
||||||
const terrainRulerAvailable = game.modules.get("terrain-ruler")?.active && (!game.modules.get("TerrainLayer")?.active || canvas.grid.type !== CONST.GRID_TYPES.GRIDLESS);
|
const terrainRulerAvailable = isToken && game.modules.get("terrain-ruler")?.active && (!game.modules.get("TerrainLayer")?.active || canvas.grid.type !== CONST.GRID_TYPES.GRIDLESS);
|
||||||
|
|
||||||
const waypoints = this.waypoints.concat([destination]);
|
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
|
// Move the waypoints to the center of the grid if a size is used that measures from edge to edge
|
||||||
const centeredWaypoints = applyTokenSizeOffset(waypoints, this.draggedEntity);
|
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
|
// Foundries native ruler requires the waypoints to sit in the dead center of the square to work properly
|
||||||
if (!terrainRulerAvailable)
|
if (!terrainRulerAvailable)
|
||||||
centeredWaypoints.forEach(w => [w.x, w.y] = canvas.grid.getCenter(w.x, w.y));
|
centeredWaypoints.forEach(w => [w.x, w.y] = canvas.grid.getCenter(w.x, w.y));
|
||||||
@@ -162,7 +169,7 @@ export function measure(destination, {gridSpaces=true, snap=false} = {}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const shape = getTokenShape(this.draggedEntity)
|
const shape = isToken ? getTokenShape(this.draggedEntity) : null;
|
||||||
|
|
||||||
// Compute measured distance
|
// Compute measured distance
|
||||||
const distances = measureDistances(centeredSegments, this.draggedEntity, shape, {gridSpaces});
|
const distances = measureDistances(centeredSegments, this.draggedEntity, shape, {gridSpaces});
|
||||||
@@ -220,7 +227,7 @@ export function measure(destination, {gridSpaces=true, snap=false} = {}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Highlight grid positions
|
// Highlight grid positions
|
||||||
if (canvas.grid.type !== CONST.GRID_TYPES.GRIDLESS) {
|
if (isToken && canvas.grid.type !== CONST.GRID_TYPES.GRIDLESS) {
|
||||||
if (terrainRulerAvailable)
|
if (terrainRulerAvailable)
|
||||||
highlightMeasurementTerrainRuler.call(this, cs.ray, cs.startDistance, shape, opacityMultiplier)
|
highlightMeasurementTerrainRuler.call(this, cs.ray, cs.startDistance, shape, opacityMultiplier)
|
||||||
else
|
else
|
||||||
|
|||||||
+32
-28
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import {currentSpeedProvider, getMovedDistanceFromToken, getRangesFromSpeedProvider, getUnreachableColorFromSpeedProvider, initApi, registerModule, registerSystem} from "./api.js"
|
import {currentSpeedProvider, getMovedDistanceFromToken, getRangesFromSpeedProvider, getUnreachableColorFromSpeedProvider, initApi, registerModule, registerSystem} from "./api.js"
|
||||||
import {checkDependencies, getHexSizeSupportTokenGridCenter} from "./compatibility.js";
|
import {checkDependencies, getHexSizeSupportTokenGridCenter} from "./compatibility.js";
|
||||||
import {moveTokens, onMouseMove} from "./foundry_imports.js"
|
import {moveEntities, onMouseMove} from "./foundry_imports.js"
|
||||||
import {performMigrations} from "./migration.js"
|
import {performMigrations} from "./migration.js"
|
||||||
import {DragRulerRuler} from "./ruler.js";
|
import {DragRulerRuler} from "./ruler.js";
|
||||||
import {getMovementHistory, resetMovementHistory} from "./movement_tracking.js";
|
import {getMovementHistory, resetMovementHistory} from "./movement_tracking.js";
|
||||||
@@ -13,7 +13,8 @@ import {SpeedProvider} from "./speed_provider.js"
|
|||||||
Hooks.once("init", () => {
|
Hooks.once("init", () => {
|
||||||
registerSettings()
|
registerSettings()
|
||||||
initApi()
|
initApi()
|
||||||
hookTokenDragHandlers()
|
hookDragHandlers(Token);
|
||||||
|
hookDragHandlers(MeasuredTemplate);
|
||||||
hookKeyboardManagerFunctions()
|
hookKeyboardManagerFunctions()
|
||||||
|
|
||||||
Ruler = DragRulerRuler;
|
Ruler = DragRulerRuler;
|
||||||
@@ -54,29 +55,29 @@ Hooks.on("getCombatTrackerEntryContext", function (html, menu) {
|
|||||||
menu.splice(1, 0, entry);
|
menu.splice(1, 0, entry);
|
||||||
});
|
});
|
||||||
|
|
||||||
function hookTokenDragHandlers() {
|
function hookDragHandlers(entityType) {
|
||||||
const originalDragLeftStartHandler = Token.prototype._onDragLeftStart
|
const originalDragLeftStartHandler = entityType.prototype._onDragLeftStart
|
||||||
Token.prototype._onDragLeftStart = function(event) {
|
entityType.prototype._onDragLeftStart = function(event) {
|
||||||
originalDragLeftStartHandler.call(this, event)
|
originalDragLeftStartHandler.call(this, event)
|
||||||
onTokenLeftDragStart.call(this, event)
|
onEntityLeftDragStart.call(this, event)
|
||||||
}
|
}
|
||||||
|
|
||||||
const originalDragLeftMoveHandler = Token.prototype._onDragLeftMove
|
const originalDragLeftMoveHandler = entityType.prototype._onDragLeftMove
|
||||||
Token.prototype._onDragLeftMove = function (event) {
|
entityType.prototype._onDragLeftMove = function (event) {
|
||||||
originalDragLeftMoveHandler.call(this, event)
|
originalDragLeftMoveHandler.call(this, event)
|
||||||
onTokenLeftDragMove.call(this, event)
|
onEntityLeftDragMove.call(this, event)
|
||||||
}
|
}
|
||||||
|
|
||||||
const originalDragLeftDropHandler = Token.prototype._onDragLeftDrop
|
const originalDragLeftDropHandler = entityType.prototype._onDragLeftDrop
|
||||||
Token.prototype._onDragLeftDrop = function (event) {
|
entityType.prototype._onDragLeftDrop = function (event) {
|
||||||
const eventHandled = onTokenDragLeftDrop.call(this, event)
|
const eventHandled = onEntityDragLeftDrop.call(this, event)
|
||||||
if (!eventHandled)
|
if (!eventHandled)
|
||||||
originalDragLeftDropHandler.call(this, event)
|
originalDragLeftDropHandler.call(this, event)
|
||||||
}
|
}
|
||||||
|
|
||||||
const originalDragLeftCancelHandler = Token.prototype._onDragLeftCancel
|
const originalDragLeftCancelHandler = entityType.prototype._onDragLeftCancel
|
||||||
Token.prototype._onDragLeftCancel = function (event) {
|
entityType.prototype._onDragLeftCancel = function (event) {
|
||||||
const eventHandled = onTokenDragLeftCancel.call(this, event)
|
const eventHandled = onEntityDragLeftCancel.call(this, event)
|
||||||
if (!eventHandled)
|
if (!eventHandled)
|
||||||
originalDragLeftCancelHandler.call(this, event)
|
originalDragLeftCancelHandler.call(this, event)
|
||||||
}
|
}
|
||||||
@@ -124,45 +125,48 @@ function onKeyShift(up) {
|
|||||||
ruler.measure(measurePosition, {snap: up})
|
ruler.measure(measurePosition, {snap: up})
|
||||||
}
|
}
|
||||||
|
|
||||||
function onTokenLeftDragStart(event) {
|
function onEntityLeftDragStart(event) {
|
||||||
if (!currentSpeedProvider.usesRuler(this))
|
const isToken = this instanceof Token;
|
||||||
|
if (isToken && !currentSpeedProvider.usesRuler(this))
|
||||||
return
|
return
|
||||||
const ruler = canvas.controls.ruler
|
const ruler = canvas.controls.ruler
|
||||||
ruler.draggedEntity = this;
|
ruler.draggedEntity = this;
|
||||||
let tokenCenter
|
let entityCenter;
|
||||||
if (canvas.grid.isHex && game.modules.get("hex-size-support")?.active && CONFIG.hexSizeSupport.getAltSnappingFlag(this))
|
if (isToken && canvas.grid.isHex && game.modules.get("hex-size-support")?.active && CONFIG.hexSizeSupport.getAltSnappingFlag(this))
|
||||||
tokenCenter = getHexSizeSupportTokenGridCenter(this)
|
entityCenter = getHexSizeSupportTokenGridCenter(this);
|
||||||
else
|
else
|
||||||
tokenCenter = this.center
|
entityCenter = this.center;
|
||||||
ruler.clear();
|
ruler.clear();
|
||||||
ruler._state = Ruler.STATES.STARTING;
|
ruler._state = Ruler.STATES.STARTING;
|
||||||
ruler.rulerOffset = {x: tokenCenter.x - event.data.origin.x, y: tokenCenter.y - event.data.origin.y}
|
ruler.rulerOffset = {x: entityCenter.x - event.data.origin.x, y: entityCenter.y - event.data.origin.y};
|
||||||
if (game.settings.get(settingsKey, "enableMovementHistory"))
|
if (isToken && game.settings.get(settingsKey, "enableMovementHistory"))
|
||||||
ruler.dragRulerAddWaypointHistory(getMovementHistory(this));
|
ruler.dragRulerAddWaypointHistory(getMovementHistory(this));
|
||||||
ruler.dragRulerAddWaypoint(tokenCenter, false);
|
ruler.dragRulerAddWaypoint(entityCenter, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onTokenLeftDragMove(event) {
|
function onEntityLeftDragMove(event) {
|
||||||
const ruler = canvas.controls.ruler
|
const ruler = canvas.controls.ruler
|
||||||
if (ruler.isDragRuler)
|
if (ruler.isDragRuler)
|
||||||
onMouseMove.call(ruler, event)
|
onMouseMove.call(ruler, event)
|
||||||
}
|
}
|
||||||
|
|
||||||
function onTokenDragLeftDrop(event) {
|
function onEntityDragLeftDrop(event) {
|
||||||
const ruler = canvas.controls.ruler
|
const ruler = canvas.controls.ruler
|
||||||
if (!ruler.isDragRuler)
|
if (!ruler.isDragRuler)
|
||||||
return false
|
return false
|
||||||
onMouseMove.call(ruler, event);
|
onMouseMove.call(ruler, event);
|
||||||
|
// When we're dragging a measured template no token will ever be selected,
|
||||||
|
// resulting in only the dragged template to be moved as would be expected
|
||||||
const selectedTokens = canvas.tokens.controlled
|
const selectedTokens = canvas.tokens.controlled
|
||||||
// This can happen if the user presses ESC during drag (maybe there are other ways too)
|
// This can happen if the user presses ESC during drag (maybe there are other ways too)
|
||||||
if (selectedTokens.length === 0)
|
if (selectedTokens.length === 0)
|
||||||
selectedTokens.push(ruler.draggedEntity);
|
selectedTokens.push(ruler.draggedEntity);
|
||||||
ruler._state = Ruler.STATES.MOVING
|
ruler._state = Ruler.STATES.MOVING
|
||||||
moveTokens.call(ruler, ruler.draggedEntity, selectedTokens);
|
moveEntities.call(ruler, ruler.draggedEntity, selectedTokens);
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
function onTokenDragLeftCancel(event) {
|
function onEntityDragLeftCancel(event) {
|
||||||
// This function is invoked by right clicking
|
// This function is invoked by right clicking
|
||||||
const ruler = canvas.controls.ruler
|
const ruler = canvas.controls.ruler
|
||||||
if (!ruler.isDragRuler || ruler._state === Ruler.STATES.MOVING)
|
if (!ruler.isDragRuler || ruler._state === Ruler.STATES.MOVING)
|
||||||
|
|||||||
+23
@@ -39,6 +39,29 @@ export function getSnapPointForToken(x, y, token) {
|
|||||||
return new PIXI.Point(snappedX + canvas.grid.w / 2, snappedY + canvas.grid.h / 2)
|
return new PIXI.Point(snappedX + canvas.grid.w / 2, snappedY + canvas.grid.h / 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getSnapPointForMeasuredTemplate(x, y) {
|
||||||
|
if (canvas.grid.type === CONST.GRID_TYPES.GRIDLESS) {
|
||||||
|
return new PIXI.Point(x, y);
|
||||||
|
}
|
||||||
|
let subgridWidth, subgridHeight;
|
||||||
|
if (canvas.grid.type === CONST.GRID_TYPES.SQUARE) {
|
||||||
|
subgridWidth = subgridHeight = canvas.dimensions.size / 2;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (canvas.grid.grid.columns) {
|
||||||
|
subgridWidth = canvas.grid.w / 4;
|
||||||
|
subgridHeight = canvas.grid.h / 2;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
subgridWidth = canvas.grid.w / 2;
|
||||||
|
subgridHeight = canvas.grid.h / 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const snappedX = Math.round(x / subgridWidth) * subgridWidth;
|
||||||
|
const snappedY = Math.round(y / subgridHeight) * subgridHeight;
|
||||||
|
return new PIXI.Point(snappedX, snappedY);
|
||||||
|
}
|
||||||
|
|
||||||
export function highlightTokenShape(position, shape, color, alpha) {
|
export function highlightTokenShape(position, shape, color, alpha) {
|
||||||
const layer = canvas.grid.highlightLayers[this.name];
|
const layer = canvas.grid.highlightLayers[this.name];
|
||||||
if ( !layer )
|
if ( !layer )
|
||||||
|
|||||||
Reference in New Issue
Block a user