v10 compat: Make Drag Ruler play nice with Foundry v10's hex grid and the new hex-size-support module

This commit is contained in:
Manuel Vögele
2022-10-15 16:00:38 +02:00
parent 01b9941c16
commit a9c15d779b
5 changed files with 110 additions and 127 deletions
-5
View File
@@ -2,11 +2,6 @@ import {buildCostFunction} from "./api.js";
import {settingsKey} from "./settings.js"; import {settingsKey} from "./settings.js";
import {highlightTokenShape} from "./util.js"; import {highlightTokenShape} from "./util.js";
export function getHexSizeSupportTokenGridCenter(token) {
const tokenCenterOffset = CONFIG.hexSizeSupport.getCenterOffset(token);
return {x: token.x + tokenCenterOffset.x, y: token.y + tokenCenterOffset.y};
}
export function highlightMeasurementTerrainRuler( export function highlightMeasurementTerrainRuler(
ray, ray,
startDistance, startDistance,
+5 -5
View File
@@ -10,7 +10,7 @@
*/ */
export function findVertexSnapPoint(x, y, altOrientationFlag) { export function findVertexSnapPoint(x, y, altOrientationFlag) {
const grid = canvas.grid.grid; const grid = canvas.grid.grid;
if (grid.columns) { if (grid.columnar) {
return findSnapPointCols(x, y, grid.h, grid.w, altOrientationFlag); return findSnapPointCols(x, y, grid.h, grid.w, altOrientationFlag);
} else { } else {
return findSnapPointRows(x, y, grid.h, grid.w, altOrientationFlag); return findSnapPointRows(x, y, grid.h, grid.w, altOrientationFlag);
@@ -59,11 +59,11 @@ function findSnapPointCols(x, y, h, w, alt) {
yOffset = -0.5; yOffset = -0.5;
} }
let xOffset1 = 0.25; let xOffset1 = 0.75;
let xOffset2 = 1.0; let xOffset2 = 0.0;
if (alt) { if (alt) {
xOffset1 = 0.75; xOffset1 = 0.25;
xOffset2 = 0.0; xOffset2 = 1.0;
} }
let row1 = calculateSnapPointsCols(x, y, h, w, xOffset1, 0.5 + yOffset); let row1 = calculateSnapPointsCols(x, y, h, w, xOffset1, 0.5 + yOffset);
+3 -11
View File
@@ -8,7 +8,7 @@ import {
registerModule, registerModule,
registerSystem, registerSystem,
} from "./api.js"; } from "./api.js";
import {checkDependencies, getHexSizeSupportTokenGridCenter} from "./compatibility.js"; import {checkDependencies} from "./compatibility.js";
import {moveEntities, onMouseMove} from "./foundry_imports.js"; import {moveEntities, onMouseMove} from "./foundry_imports.js";
import {disableSnap, registerKeybindings} from "./keybindings.js"; import {disableSnap, registerKeybindings} from "./keybindings.js";
import {libWrapper} from "./libwrapper_shim.js"; import {libWrapper} from "./libwrapper_shim.js";
@@ -18,7 +18,7 @@ import {extendRuler} from "./ruler.js";
import {registerSettings, RightClickAction, settingsKey} from "./settings.js"; import {registerSettings, RightClickAction, settingsKey} from "./settings.js";
import {recalculate} from "./socket.js"; import {recalculate} from "./socket.js";
import {SpeedProvider} from "./speed_provider.js"; import {SpeedProvider} from "./speed_provider.js";
import {setSnapParameterOnOptions} from "./util.js"; import {getEntityCenter, setSnapParameterOnOptions} from "./util.js";
CONFIG.debug.dragRuler = false; CONFIG.debug.dragRuler = false;
export let debugGraphics = undefined; export let debugGraphics = undefined;
@@ -136,15 +136,7 @@ function onEntityLeftDragStart(wrapped, event) {
const isToken = this instanceof Token; const isToken = this instanceof Token;
const ruler = canvas.controls.ruler; const ruler = canvas.controls.ruler;
ruler.draggedEntity = this; ruler.draggedEntity = this;
let entityCenter; const entityCenter = getEntityCenter(this);
if (
isToken &&
canvas.grid.isHex &&
game.modules.get("hex-size-support")?.active &&
CONFIG.hexSizeSupport.getAltSnappingFlag(this)
)
entityCenter = getHexSizeSupportTokenGridCenter(this);
else entityCenter = this.center;
ruler.rulerOffset = { ruler.rulerOffset = {
x: entityCenter.x - event.data.origin.x, x: entityCenter.x - event.data.origin.x,
y: entityCenter.y - event.data.origin.y, y: entityCenter.y - event.data.origin.y,
+3 -14
View File
@@ -3,11 +3,7 @@ import {
getColorForDistanceAndToken, getColorForDistanceAndToken,
getRangesFromSpeedProvider, getRangesFromSpeedProvider,
} from "./api.js"; } from "./api.js";
import { import {highlightMeasurementTerrainRuler, measureDistances} from "./compatibility.js";
getHexSizeSupportTokenGridCenter,
highlightMeasurementTerrainRuler,
measureDistances,
} from "./compatibility.js";
import {getGridPositionFromPixelsObj, getPixelsFromGridPositionObj} from "./foundry_fixes.js"; import {getGridPositionFromPixelsObj, getPixelsFromGridPositionObj} from "./foundry_fixes.js";
import {cancelScheduledMeasurement, highlightMeasurementNative} from "./foundry_imports.js"; import {cancelScheduledMeasurement, highlightMeasurementNative} from "./foundry_imports.js";
import {disableSnap} from "./keybindings.js"; import {disableSnap} from "./keybindings.js";
@@ -17,6 +13,7 @@ import {
applyTokenSizeOffset, applyTokenSizeOffset,
getSnapPointForEntity, getSnapPointForEntity,
getSnapPointForTokenObj, getSnapPointForTokenObj,
getEntityCenter,
getTokenShape, getTokenShape,
isPathfindingEnabled, isPathfindingEnabled,
} from "./util.js"; } from "./util.js";
@@ -482,15 +479,7 @@ export function extendRuler() {
const ruler = canvas.controls.ruler; const ruler = canvas.controls.ruler;
ruler.clear(); ruler.clear();
ruler._state = Ruler.STATES.STARTING; ruler._state = Ruler.STATES.STARTING;
let entityCenter; const entityCenter = getEntityCenter(this.draggedEntity);
if (
isToken &&
canvas.grid.isHex &&
game.modules.get("hex-size-support")?.active &&
CONFIG.hexSizeSupport.getAltSnappingFlag(entity)
)
entityCenter = getHexSizeSupportTokenGridCenter(entity);
else entityCenter = entity.center;
if (isToken && game.settings.get(settingsKey, "enableMovementHistory")) if (isToken && game.settings.get(settingsKey, "enableMovementHistory"))
ruler.dragRulerAddWaypointHistory(getMovementHistory(entity)); ruler.dragRulerAddWaypointHistory(getMovementHistory(entity));
ruler.dragRulerAddWaypoint(entityCenter, {snap: false}); ruler.dragRulerAddWaypoint(entityCenter, {snap: false});
+99 -92
View File
@@ -27,83 +27,99 @@ export function sum(arr) {
return arr.reduce((a, b) => a + b, 0); return arr.reduce((a, b) => a + b, 0);
} }
export function buildSnapPointTokenData(token) { export function getHexTokenSize(token) {
const tokenData = { const size = token.document.width;
width: token.document.width, if (token.document.height !== size) {
height: token.document.height, return 1;
};
if (isModuleActive("hex-size-support")) {
tokenData.hexSizeSupport = {};
tokenData.hexSizeSupport.altSnappingFlag = CONFIG.hexSizeSupport.getAltSnappingFlag(token);
tokenData.hexSizeSupport.altOrientationFlag =
CONFIG.hexSizeSupport.getAltOrientationFlag(token);
tokenData.hexSizeSupport.borderSize = token.document.getFlag("hex-size-support", "borderSize");
} }
return size;
return tokenData;
} }
export function getSnapPointForToken(x, y, token) { export function getEntityCenter(token) {
return getSnapPointForTokenData(x, y, buildSnapPointTokenData(token)); if (token instanceof Token && canvas.grid.isHex) {
const center = token.center;
const size = getHexTokenSize(token);
if (size % 2 === 0) {
let offset;
if (canvas.grid.grid.columnar) {
offset = canvas.grid.grid.w - canvas.grid.grid.h;
} else {
offset = canvas.grid.grid.h - canvas.grid.grid.w;
}
if (getAltOrientationFlagForToken(token, size)) {
offset *= -1;
}
if (canvas.grid.grid.columnar) {
center.x -= offset;
return center;
} else {
center.y -= offset;
return center;
}
}
}
return token.center;
} }
export function getSnapPointForTokenDataObj(pos, tokenData) { export function getAltOrientationFlagForToken(token, size) {
return getSnapPointForTokenData(pos.x, pos.y, tokenData); const hexSizeSupport = game.modules.get("hex-size-support").api;
if (hexSizeSupport) {
return hexSizeSupport.isAltOrientation(token);
}
// In native foundry, tokens of size 2 are oriented like the "alt orientation" from hex-size-support
// Tokens of size 4 are oriented like alt orientation wasn't set
return size === 2;
} }
// A copy of this function lives in the librouting module // A copy of this function lives in the librouting module
function getSnapPointForTokenData(x, y, tokenData) { export function getSnapPointForToken(x, y, token) {
if (canvas.grid.type === CONST.GRID_TYPES.GRIDLESS) { if (canvas.grid.type === CONST.GRID_TYPES.GRIDLESS) {
return new PIXI.Point(x, y); return {x, y};
} }
if (canvas.grid.isHex) { if (canvas.grid.isHex) {
if (tokenData.hexSizeSupport?.altSnappingFlag) { const size = getHexTokenSize(token);
if (tokenData.hexSizeSupport.borderSize % 2 === 0) { if (size % 2 === 0) {
const snapPoint = findVertexSnapPoint(x, y, tokenData.hexSizeSupport.altOrientationFlag); return findVertexSnapPoint(x, y, getAltOrientationFlagForToken(token, size));
return new PIXI.Point(snapPoint.x, snapPoint.y);
} else {
return new PIXI.Point(...canvas.grid.getCenter(x, y));
}
} else {
return new PIXI.Point(...canvas.grid.getCenter(x, y));
} }
const [snapX, snapY] = canvas.grid.getCenter(x, y);
return {x: snapX, y: snapY};
} }
const [topLeftX, topLeftY] = canvas.grid.getTopLeft(x, y); const [topLeftX, topLeftY] = canvas.grid.getTopLeft(x, y);
let cellX, cellY; let cellX, cellY;
if (tokenData.width % 2 === 0) cellX = x - canvas.grid.h / 2; if (token.width % 2 === 0) cellX = x - canvas.grid.h / 2;
else cellX = x; else cellX = x;
if (tokenData.height % 2 === 0) cellY = y - canvas.grid.h / 2; if (token.height % 2 === 0) cellY = y - canvas.grid.h / 2;
else cellY = y; else cellY = y;
const [centerX, centerY] = canvas.grid.getCenter(cellX, cellY); const [centerX, centerY] = canvas.grid.getCenter(cellX, cellY);
let snapX, snapY; let snapX, snapY;
// Tiny tokens can snap to the cells corners // Tiny tokens can snap to the cells corners
if (tokenData.width <= 0.5) { if (token.width <= 0.5) {
const offsetX = x - topLeftX; const offsetX = x - topLeftX;
const subGridWidth = Math.floor(canvas.grid.w / 2); const subGridWidth = Math.floor(canvas.grid.w / 2);
const subGridPosX = Math.floor(offsetX / subGridWidth); const subGridPosX = Math.floor(offsetX / subGridWidth);
snapX = topLeftX + (subGridPosX + 0.5) * subGridWidth; snapX = topLeftX + (subGridPosX + 0.5) * subGridWidth;
} }
// Tokens with odd multipliers (1x1, 3x3, ...) and tokens smaller than 1x1 but bigger than 0.5x0.5 snap to the center of the grid cell // Tokens with odd multipliers (1x1, 3x3, ...) and tokens smaller than 1x1 but bigger than 0.5x0.5 snap to the center of the grid cell
else if (Math.round(tokenData.width) % 2 === 1 || tokenData.width < 1) { else if (Math.round(token.width) % 2 === 1 || token.width < 1) {
snapX = centerX; snapX = centerX;
} }
// All remaining tokens (those with even or fractional multipliers on square grids) snap to the intersection points of the grid // All remaining tokens (those with even or fractional multipliers on square grids) snap to the intersection points of the grid
else { else {
snapX = centerX + canvas.grid.w / 2; snapX = centerX + canvas.grid.w / 2;
} }
if (tokenData.height <= 0.5) { if (token.height <= 0.5) {
const offsetY = y - topLeftY; const offsetY = y - topLeftY;
const subGridHeight = Math.floor(canvas.grid.h / 2); const subGridHeight = Math.floor(canvas.grid.h / 2);
const subGridPosY = Math.floor(offsetY / subGridHeight); const subGridPosY = Math.floor(offsetY / subGridHeight);
snapY = topLeftY + (subGridPosY + 0.5) * subGridHeight; snapY = topLeftY + (subGridPosY + 0.5) * subGridHeight;
} else if (Math.round(tokenData.height) % 2 === 1 || tokenData.height < 1) { } else if (Math.round(token.height) % 2 === 1 || token.height < 1) {
snapY = centerY; snapY = centerY;
} else { } else {
snapY = centerY + canvas.grid.h / 2; snapY = centerY + canvas.grid.h / 2;
} }
return new PIXI.Point(snapX, snapY); return {x: snapX, y: snapY};
} }
export function getSnapPointForTokenObj(pos, token) { export function getSnapPointForTokenObj(pos, token) {
@@ -141,7 +157,7 @@ export function getAreaFromPositionAndShape(position, shape) {
let shiftedRow; let shiftedRow;
if (canvas.grid.grid.options.even) shiftedRow = 1; if (canvas.grid.grid.options.even) shiftedRow = 1;
else shiftedRow = 0; else shiftedRow = 0;
if (canvas.grid.grid.options.columns) { if (canvas.grid.grid.columnar) {
if (space.x % 2 !== 0 && position.x % 2 !== shiftedRow) { if (space.x % 2 !== 0 && position.x % 2 !== shiftedRow) {
y += 1; y += 1;
} }
@@ -156,66 +172,59 @@ export function getAreaFromPositionAndShape(position, shape) {
} }
export function getTokenShape(token) { export function getTokenShape(token) {
return getTokenShapeForTokenData(buildSnapPointTokenData(token), token.scene); let scene = canvas.scene;
}
export function getTokenShapeForTokenData(tokenData, scene = canvas.scene) {
if (scene.grid.type === CONST.GRID_TYPES.GRIDLESS) { if (scene.grid.type === CONST.GRID_TYPES.GRIDLESS) {
return [{x: 0, y: 0}]; return [{x: 0, y: 0}];
} else if (scene.grid.type === CONST.GRID_TYPES.SQUARE) { } else if (scene.grid.type === CONST.GRID_TYPES.SQUARE) {
const topOffset = -Math.floor(tokenData.height / 2); const topOffset = -Math.floor(token.height / 2);
const leftOffset = -Math.floor(tokenData.width / 2); const leftOffset = -Math.floor(token.width / 2);
const shape = []; const shape = [];
for (let y = 0; y < tokenData.height; y++) { for (let y = 0; y < token.height; y++) {
for (let x = 0; x < tokenData.width; x++) { for (let x = 0; x < token.width; x++) {
shape.push({x: x + leftOffset, y: y + topOffset}); shape.push({x: x + leftOffset, y: y + topOffset});
} }
} }
return shape; return shape;
} else { } else {
// Hex grids // Hex grids
if (game.modules.get("hex-size-support")?.active && tokenData.hexSizeSupport.altSnappingFlag) { const size = getHexTokenSize(token);
const borderSize = tokenData.hexSizeSupport.borderSize; let shape = [{x: 0, y: 0}];
let shape = [{x: 0, y: 0}]; if (size >= 2)
if (borderSize >= 2) shape = shape.concat([
shape = shape.concat([ {x: 0, y: -1},
{x: 0, y: -1}, {x: -1, y: -1},
{x: -1, y: -1}, ]);
]); if (size >= 3)
if (borderSize >= 3) shape = shape.concat([
shape = shape.concat([ {x: 0, y: 1},
{x: 0, y: 1}, {x: -1, y: 1},
{x: -1, y: 1}, {x: -1, y: 0},
{x: -1, y: 0}, {x: 1, y: 0},
{x: 1, y: 0}, ]);
]); if (size >= 4)
if (borderSize >= 4) shape = shape.concat([
shape = shape.concat([ {x: -2, y: -1},
{x: -2, y: -1}, {x: 1, y: -1},
{x: 1, y: -1}, {x: -1, y: -2},
{x: -1, y: -2}, {x: 0, y: -2},
{x: 0, y: -2}, {x: 1, y: -2},
{x: 1, y: -2}, ]);
]);
if (Boolean(tokenData.hexSizeSupport.altOrientationFlag) !== canvas.grid.grid.options.columns) if (getAltOrientationFlagForToken(token, size)) {
shape.forEach(space => (space.y *= -1)); shape.forEach(space => (space.y *= -1));
if (canvas.grid.grid.options.columns)
shape = shape.map(space => {
return {x: space.y, y: space.x};
});
return shape;
} else {
return [{x: 0, y: 0}];
} }
if (canvas.grid.grid.columnar)
shape = shape.map(space => {
return {x: space.y, y: space.x};
});
return shape;
} }
} }
export function getTokenSize(token) { export function getTokenSize(token) {
let w, h; let w, h;
const hexSizeSupportBorderSize = token.document.flags["hex-size-support"]?.borderSize; if (canvas.grid.isHex) {
if (hexSizeSupportBorderSize > 0) { w = h = getHexTokenSize(token);
w = h = hexSizeSupportBorderSize;
} else { } else {
w = token.document.width; w = token.document.width;
h = token.document.height; h = token.document.height;
@@ -233,18 +242,16 @@ export function applyTokenSizeOffset(waypoints, token) {
const tokenSize = getTokenSize(token); const tokenSize = getTokenSize(token);
const waypointOffset = {x: 0, y: 0}; const waypointOffset = {x: 0, y: 0};
if (canvas.grid.isHex) { if (canvas.grid.isHex) {
if (game.modules.get("hex-size-support")?.active) { const isAltOrientation = getAltOrientationFlagForToken(token, getHexTokenSize(token));
const isAltOrientation = CONFIG.hexSizeSupport.getAltOrientationFlag(token); if (canvas.grid.grid.columnar) {
if (canvas.grid.grid.options.columns) { if (tokenSize.w % 2 === 0) {
if (tokenSize.w % 2 === 0) { waypointOffset.x = canvas.grid.w / 2;
waypointOffset.x = canvas.grid.w / 2; if (isAltOrientation) waypointOffset.x *= -1;
if (!isAltOrientation) waypointOffset.x *= -1; }
} } else {
} else { if (tokenSize.h % 2 === 0) {
if (tokenSize.h % 2 === 0) { waypointOffset.y = canvas.grid.h / 2;
waypointOffset.y = canvas.grid.h / 2; if (isAltOrientation) waypointOffset.y *= -1;
if (isAltOrientation) waypointOffset.y *= -1;
}
} }
} }
// If hex size support isn't active leave the waypoints like they are // If hex size support isn't active leave the waypoints like they are