Code changes for v9 compatibility (moves keybindings into the new foundry API)

This commit is contained in:
Manuel Vögele
2022-01-02 18:28:32 +01:00
parent b06169f149
commit 52d77ba0a4
14 changed files with 364 additions and 254 deletions
+3 -2
View File
@@ -1,6 +1,7 @@
import {highlightMeasurementTerrainRuler, measureDistances} from "./compatibility.js";
import {getGridPositionFromPixels} from "./foundry_fixes.js";
import {Line} from "./geometry.js";
import {disableSnap, moveWithoutAnimation} from "./keybindings.js";
import {trackRays} from "./movement_tracking.js"
import {recalculate} from "./socket.js";
import {applyTokenSizeOffset, getSnapPointForEntity, getSnapPointForToken, getTokenShape, highlightTokenShape, zip} from "./util.js";
@@ -69,7 +70,7 @@ async function animateEntities(entities, draggedEntity, draggedRays, wasPaused)
});
const isToken = draggedEntity instanceof Token;
const animate = isToken && !game.keyboard.isDown("Alt");
const animate = isToken && !moveWithoutAnimation;
const startWaypoint = animate ? 0 : entityAnimationData[0].rays.length - 1;
// This is a flag of the "Monk's Active Tile Triggers" module that signals that the movement should be cancelled early
@@ -130,7 +131,7 @@ function scheduleMeasurement(destination, event) {
const mt = event._measureTime || 0;
const originalEvent = event.data.originalEvent;
if (Date.now() - mt > measurementInterval) {
this.measure(destination, {snap: !originalEvent.shiftKey});
this.measure(destination, {snap: !disableSnap});
event._measureTime = Date.now();
this._state = Ruler.STATES.MEASURING;
cancelScheduledMeasurement.call(this);
+105
View File
@@ -0,0 +1,105 @@
import {settingsKey} from "./settings.js";
import { getMeasurePosition, setSnapParameterOnOptions } from "./util.js";
export let disableSnap = false;
export let moveWithoutAnimation = false;
export function registerKeybindings() {
game.keybindings.register(settingsKey, "cancelDrag", {
name: "drag-ruler.keybindings.cancelDrag",
onDown: cancelDrag,
uneditable: [{
key: "Escape",
}],
precedence: -1,
});
game.keybindings.register(settingsKey, "createWaypoint", {
name: "drag-ruler.keybindings.createWaypoint",
onDown: handleCreateWaypoint,
editable: [{
key: "Space"
}],
precedence: -1,
});
game.keybindings.register(settingsKey, "deleteWaypoint", {
name: "drag-ruler.keybindings.deleteWaypoint",
onDown: handleDeleteWaypoint,
precedence: -1,
});
game.keybindings.register(settingsKey, "disableSnap", {
name: "drag-ruler.keybindings.disableSnap.name",
hint: "drag-ruler.keybindings.disableSnap.hint",
onDown: handleDisableSnap,
onUp: handleDisableSnap,
editable: [{
key: "ShiftLeft",
}],
precedence: -1,
});
game.keybindings.register(settingsKey, "moveWithoutAnimation", {
name: "drag-ruler.keybindings.moveWithoutAnimation.name",
hint: "drag-ruler.keybindings.moveWithoutAnimation.hint",
onDown: handleMoveWithoutAnimation,
onUp: handleMoveWithoutAnimation,
editable: [{
key: "AltLeft",
}],
precedence: -1,
});
}
function handleDeleteWaypoint() {
const ruler = canvas.controls.ruler;
if (!ruler.draggedEntity)
return false;
ruler.dragRulerDeleteWaypoint();
return true;
}
function handleCreateWaypoint() {
const ruler = canvas.controls.ruler;
// .draggedEntity is used here because .isDragRuler only returns true once the ruler started measuring
// Ruler can end up being undefined here if no canvas is active
if (!ruler?.draggedEntity)
return false;
let options = {};
setSnapParameterOnOptions(ruler, options);
if (ruler._state === Ruler.STATES.INACTIVE) {
ruler.dragRulerStart(options);
}
else {
ruler.dragRulerAddWaypoint(getMeasurePosition(), options);
}
return true;
}
function cancelDrag() {
const ruler = canvas.controls.ruler;
if (!ruler.draggedEntity)
return false;
ruler.dragRulerAbortDrag();
return true;
}
function handleDisableSnap(event) {
disableSnap = !event.up;
const ruler = canvas.controls.ruler;
if (!ruler.isDragRuler)
return false;
if (ruler._state !== Ruler.STATES.MEASURING)
return false;
ruler.measure(getMeasurePosition(), {snap: !disableSnap});
return false;
}
function handleMoveWithoutAnimation(event) {
moveWithoutAnimation = !event.up;
}
+22 -105
View File
@@ -1,23 +1,24 @@
"use strict"
import {currentSpeedProvider, getColorForDistanceAndToken, getMovedDistanceFromToken, getRangesFromSpeedProvider, initApi, registerModule, registerSystem} from "./api.js";
import {getColorForDistanceAndToken, getMovedDistanceFromToken, getRangesFromSpeedProvider, initApi, registerModule, registerSystem} from "./api.js";
import {checkDependencies, getHexSizeSupportTokenGridCenter, highlightMeasurementTerrainRuler} from "./compatibility.js";
import {moveEntities, onMouseMove} from "./foundry_imports.js"
import {disableSnap, registerKeybindings} from "./keybindings.js";
import {libWrapper} from "./libwrapper_shim.js";
import {performMigrations} from "./migration.js"
import {getMovementHistory, removeLastHistoryEntryIfAt, resetMovementHistory} from "./movement_tracking.js";
import {removeLastHistoryEntryIfAt, resetMovementHistory} from "./movement_tracking.js";
import {extendRuler} from "./ruler.js";
import {registerSettings, settingsKey} from "./settings.js"
import {registerSettings, RightClickAction, settingsKey} from "./settings.js"
import {recalculate} from "./socket.js";
import {SpeedProvider} from "./speed_provider.js"
import {isClose, setSnapParameterOnOptions} from "./util.js";
Hooks.once("init", () => {
registerSettings()
registerKeybindings()
initApi()
hookDragHandlers(Token);
hookDragHandlers(MeasuredTemplate);
libWrapper.register("drag-ruler", "KeyboardManager.prototype._handleKeys", forwardIfUnahndled(handleKeys), "MIXED");
libWrapper.register("drag-ruler", "TokenLayer.prototype.undoHistory", tokenLayerUndoHistory, "WRAPPER");
extendRuler();
@@ -89,74 +90,6 @@ async function tokenLayerUndoHistory(wrapped) {
return returnValue;
}
function handleKeys(event, key, up) {
if (event.repeat || this.hasFocus)
return false
const lowercaseKey = key.toLowerCase();
if (lowercaseKey === "x") return onKeyX(up)
if (lowercaseKey === "shift") return onKeyShift(up)
if (lowercaseKey === "space") return onKeySpace(up);
if (lowercaseKey === "escape") return onKeyEscape(up);
return false
}
function onKeyX(up) {
if (up)
return false
const ruler = canvas.controls.ruler;
if (!ruler.isDragRuler)
return false
ruler.dragRulerDeleteWaypoint();
return true
}
function onKeyShift(up) {
const ruler = canvas.controls.ruler
if (!ruler.isDragRuler)
return false
if (ruler._state !== Ruler.STATES.MEASURING)
return false;
const mousePosition = canvas.app.renderer.plugins.interaction.mouse.getLocalPosition(canvas.tokens)
const rulerOffset = ruler.rulerOffset
const measurePosition = {x: mousePosition.x + rulerOffset.x, y: mousePosition.y + rulerOffset.y}
ruler.measure(measurePosition, {snap: up})
}
function onKeySpace(up) {
const ruler = canvas.controls.ruler;
// Ruler can end up being undefined here if no canvas is active
if (!ruler?.draggedEntity)
return false;
if (ruler._state !== Ruler.STATES.INACTIVE)
return false;
const swapSpacebarRightClick = game.settings.get(settingsKey, "swapSpacebarRightClick");
let options = {};
setSnapParameterOnOptions(ruler, options);
if (!up) {
if (swapSpacebarRightClick)
ruler.dragRulerAbortDrag();
else
startDragRuler.call(ruler.draggedEntity, options);
}
return true;
}
function onKeyEscape(up) {
const ruler = canvas.controls.ruler;
if (!ruler.draggedEntity)
return false;
if (!up)
ruler.dragRulerAbortDrag();
return true;
}
function onEntityLeftDragStart(wrapped, event) {
wrapped(event);
const isToken = this instanceof Token;
@@ -171,31 +104,10 @@ function onEntityLeftDragStart(wrapped, event) {
if (game.settings.get(settingsKey, "autoStartMeasurement")) {
let options = {};
setSnapParameterOnOptions(ruler, options);
startDragRuler.call(this, options, false);
ruler.dragRulerStart(options, false);
}
}
function startDragRuler(options, measureImmediately=true) {
const isToken = this instanceof Token;
if (isToken && !currentSpeedProvider.usesRuler(this))
return;
const ruler = canvas.controls.ruler;
ruler.clear();
ruler._state = Ruler.STATES.STARTING;
let entityCenter;
if (isToken && canvas.grid.isHex && game.modules.get("hex-size-support")?.active && CONFIG.hexSizeSupport.getAltSnappingFlag(this))
entityCenter = getHexSizeSupportTokenGridCenter(this);
else
entityCenter = this.center;
if (isToken && game.settings.get(settingsKey, "enableMovementHistory"))
ruler.dragRulerAddWaypointHistory(getMovementHistory(this));
ruler.dragRulerAddWaypoint(entityCenter, {snap: false});
const mousePosition = canvas.app.renderer.plugins.interaction.mouse.getLocalPosition(canvas.tokens);
const destination = {x: mousePosition.x + ruler.rulerOffset.x, y: mousePosition.y + ruler.rulerOffset.y};
if (measureImmediately)
ruler.measure(destination, options);
}
function onEntityLeftDragMoveSnap(wrapped, event) {
applyGridlessSnapping.call(this, event);
onEntityLeftDragMove.call(this, wrapped, event);
@@ -231,26 +143,31 @@ function onEntityDragLeftCancel(event) {
if (!ruler.draggedEntity || ruler._state === Ruler.STATES.MOVING)
return false
const swapSpacebarRightClick = game.settings.get(settingsKey, "swapSpacebarRightClick");
const rightClickAction = game.settings.get(settingsKey, "rightClickAction");
let options = {};
setSnapParameterOnOptions(ruler, options);
if (ruler._state === Ruler.STATES.INACTIVE) {
if (!swapSpacebarRightClick)
if (rightClickAction !== RightClickAction.CREATE_WAYPOINT)
return false;
startDragRuler.call(this, options);
ruler.dragRulerStart(options);
event.preventDefault();
}
else if (ruler._state === Ruler.STATES.MEASURING) {
if (!swapSpacebarRightClick) {
ruler.dragRulerDeleteWaypoint(event, options);
}
else {
event.preventDefault();
ruler.dragRulerAddWaypoint(ruler.destination, options);
switch (rightClickAction) {
case RightClickAction.CREATE_WAYPOINT:
event.preventDefault();
ruler.dragRulerAddWaypoint(ruler.destination, options);
break;
case RightClickAction.DELETE_WAYPOINT:
ruler.dragRulerDeleteWaypoint(event, options);
break;
case RightClickAction.ABORT_DRAG:
ruler.dragRulerAbortDrag();
break;
}
}
return true
return true;
}
function applyGridlessSnapping(event) {
@@ -259,7 +176,7 @@ function applyGridlessSnapping(event) {
return;
if (!ruler.isDragRuler)
return;
if (game.keyboard.isDown("Shift"))
if (disableSnap)
return;
if (canvas.grid.type !== CONST.GRID_TYPES.GRIDLESS)
return;
+35 -6
View File
@@ -1,14 +1,43 @@
import {settingsKey} from "./settings.js"
import {RightClickAction, settingsKey} from "./settings.js"
const currentDataVersion = "1.3.0"
const currentDataVersion = "1.10.0"
export function performMigrations() {
if (!game.user.isGM)
return
export async function performMigrations() {
if (game.user.isGM)
await performWorldMigraionts()
await performClientMigrations()
}
async function performWorldMigraionts() {
let dataVersion = game.settings.get(settingsKey, "dataVersion");
if (dataVersion === currentDataVersion)
return;
let dataVersion = game.settings.get(settingsKey, "dataVersion")
if (dataVersion === "fresh install") {
game.settings.set(settingsKey, "dataVersion", currentDataVersion)
return
}
if (dataVersion === "1.3.0") {
dataVersion = "1.10.0"
}
game.settings.set(settingsKey, "dataVersion", dataVersion);
}
async function performClientMigrations() {
let dataVersion = game.settings.get(settingsKey, "clientDataVersion");
if (dataVersion === "fresh install") {
// Start of migration from unnamed version (< 1.10.0). TODO Remove in a future version
const swapSpacebarRightClick = game.settings.storage.get("client").getItem(`${settingsKey}.swapSpacebarRightClick`);
if (swapSpacebarRightClick) {
game.settings.set(settingsKey, "rightClickAction", RightClickAction.CREATE_WAYPOINT);
await game.keybindings.set(settingsKey, "createWaypoint", []);
await game.keybindings.set(settingsKey, "deleteWaypoint", [{key: "Space"}]);
}
// End of migration from unnamed version
game.settings.set(settingsKey, "clientDataVersion", currentDataVersion)
}
}
+25 -12
View File
@@ -1,4 +1,5 @@
import {getColorForDistanceAndToken, getRangesFromSpeedProvider} from "./api.js";
import {currentSpeedProvider, getColorForDistanceAndToken, getRangesFromSpeedProvider} from "./api.js";
import {getHexSizeSupportTokenGridCenter} from "./compatibility.js";
import {cancelScheduledMeasurement, measure} from "./foundry_imports.js"
import {getMovementHistory} from "./movement_tracking.js";
import {settingsKey} from "./settings.js";
@@ -22,19 +23,9 @@ export function extendRuler() {
}
async moveToken(event) {
// This function is invoked by left clicking
// Disable moveToken if Drag Ruler is active
if (!this.isDragRuler)
return await super.moveToken(event);
let options = {};
setSnapParameterOnOptions(this, options);
if (!game.settings.get(settingsKey, "swapSpacebarRightClick")) {
this.dragRulerAddWaypoint(this.destination, options);
}
else {
this.dragRulerDeleteWaypoint(event, options);
}
}
toJSON() {
@@ -172,6 +163,28 @@ export function extendRuler() {
this.dragRulerRanges = getRangesFromSpeedProvider(this.draggedEntity);
return getColorForDistanceAndToken(distance, this.draggedEntity, this.dragRulerRanges) ?? this.color;
}
dragRulerStart(options, measureImmediately=true) {
const entity = this.draggedEntity;
const isToken = entity instanceof Token;
if (isToken && !currentSpeedProvider.usesRuler(entity))
return;
const ruler = canvas.controls.ruler;
ruler.clear();
ruler._state = Ruler.STATES.STARTING;
let entityCenter;
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"))
ruler.dragRulerAddWaypointHistory(getMovementHistory(entity));
ruler.dragRulerAddWaypoint(entityCenter, {snap: false});
const mousePosition = canvas.app.renderer.plugins.interaction.mouse.getLocalPosition(canvas.tokens);
const destination = {x: mousePosition.x + ruler.rulerOffset.x, y: mousePosition.y + ruler.rulerOffset.y};
if (measureImmediately)
ruler.measure(destination, options);
}
}
Ruler = DragRulerRuler;
+26 -9
View File
@@ -3,6 +3,12 @@ import {SpeedProvider} from "./speed_provider.js"
export const settingsKey = "drag-ruler";
export const RightClickAction = Object.freeze({
CREATE_WAYPOINT: 0,
DELETE_WAYPOINT: 1,
ABORT_DRAG:2,
});
export function registerSettings() {
game.settings.register(settingsKey, "dataVersion", {
scope: "world",
@@ -11,6 +17,26 @@ export function registerSettings() {
default: "fresh install"
})
game.settings.register(settingsKey, "clientDataVersion", {
scope: "client",
config: false,
type: String,
default: "fresh install"
});
game.settings.register(settingsKey, "rightClickAction", {
name: "drag-ruler.settings.rightClickAction.name",
hint: "drag-ruler.settings.rightClickAction.hint",
config: true,
type: Number,
default: RightClickAction.DELETE_WAYPOINT,
choices: {
0: "drag-ruler.settings.rightClickAction.choices.create",
1: "drag-ruler.settings.rightClickAction.choices.delete",
2: "drag-ruler.settings.rightClickAction.choices.cancel",
},
});
game.settings.register(settingsKey, "autoStartMeasurement", {
name: "drag-ruler.settings.autoStartMeasurement.name",
hint: "drag-ruler.settings.autoStartMeasurement.hint",
@@ -20,15 +46,6 @@ export function registerSettings() {
default: true,
});
game.settings.register(settingsKey, "swapSpacebarRightClick", {
name: "drag-ruler.settings.swapSpacebarRightClick.name",
hint: "drag-ruler.settings.swapSpacebarRightClick.hint",
scope: "client",
config: true,
type: Boolean,
default: false,
})
game.settings.register(settingsKey, "useGridlessRaster", {
name: "drag-ruler.settings.useGridlessRaster.name",
hint: "drag-ruler.settings.useGridlessRaster.hint",
+9 -1
View File
@@ -1,4 +1,5 @@
import {getPixelsFromGridPosition} from "./foundry_fixes.js"
import { disableSnap } from "./keybindings.js";
export function* zip(it1, it2) {
for (let i = 0;i < Math.min(it1.length, it2.length);i++) {
@@ -235,10 +236,17 @@ export function setSnapParameterOnOptions(sourceObject, options) {
sourceObject.snapOverride = undefined; // remove it to prevent any lingering data issues
}
else {
options.snap = !game.keyboard._downKeys.has("Shift");
options.snap = !disableSnap;
}
}
export function isClose(a, b, delta) {
return Math.abs(a - b) <= delta;
}
export function getMeasurePosition() {
const mousePosition = canvas.app.renderer.plugins.interaction.mouse.getLocalPosition(canvas.tokens);
const rulerOffset = canvas.controls.ruler.rulerOffset;
const measurePosition = {x: mousePosition.x + rulerOffset.x, y: mousePosition.y + rulerOffset.y};
return measurePosition;
}