Immediately override the Ruler after extension to increase interoperability with other modules
This commit is contained in:
+2
-2
@@ -4,8 +4,8 @@ import {currentSpeedProvider, getColorForDistanceAndToken, getMovedDistanceFromT
|
|||||||
import {checkDependencies, getHexSizeSupportTokenGridCenter, highlightMeasurementTerrainRuler} from "./compatibility.js";
|
import {checkDependencies, getHexSizeSupportTokenGridCenter, highlightMeasurementTerrainRuler} from "./compatibility.js";
|
||||||
import {moveEntities, 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 {getMovementHistory, removeLastHistoryEntryIfAt, resetMovementHistory} from "./movement_tracking.js";
|
import {getMovementHistory, removeLastHistoryEntryIfAt, resetMovementHistory} from "./movement_tracking.js";
|
||||||
|
import {extendRuler} from "./ruler.js";
|
||||||
import {registerSettings, settingsKey} from "./settings.js"
|
import {registerSettings, 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"
|
||||||
@@ -19,7 +19,7 @@ Hooks.once("init", () => {
|
|||||||
hookKeyboardManagerFunctions()
|
hookKeyboardManagerFunctions()
|
||||||
hookLayerFunctions();
|
hookLayerFunctions();
|
||||||
|
|
||||||
Ruler = DragRulerRuler;
|
extendRuler();
|
||||||
|
|
||||||
window.dragRuler = {
|
window.dragRuler = {
|
||||||
getColorForDistanceAndToken,
|
getColorForDistanceAndToken,
|
||||||
|
|||||||
+152
-148
@@ -4,171 +4,175 @@ import {getMovementHistory} from "./movement_tracking.js";
|
|||||||
import {settingsKey} from "./settings.js";
|
import {settingsKey} from "./settings.js";
|
||||||
import {getSnapPointForEntity, setSnapParameterOnOptions} from "./util.js";
|
import {getSnapPointForEntity, setSnapParameterOnOptions} from "./util.js";
|
||||||
|
|
||||||
export class DragRulerRuler extends Ruler {
|
export function extendRuler() {
|
||||||
// Functions below are overridden versions of functions in Ruler
|
class DragRulerRuler extends Ruler {
|
||||||
constructor(user, {color=null}={}) {
|
// Functions below are overridden versions of functions in Ruler
|
||||||
super(user, {color});
|
constructor(user, {color=null}={}) {
|
||||||
this.previousWaypoints = [];
|
super(user, {color});
|
||||||
this.previousLabels = this.addChild(new PIXI.Container());
|
this.previousWaypoints = [];
|
||||||
}
|
this.previousLabels = this.addChild(new PIXI.Container());
|
||||||
|
|
||||||
clear() {
|
|
||||||
super.clear();
|
|
||||||
this.previousWaypoints = [];
|
|
||||||
this.previousLabels.removeChildren().forEach(c => c.destroy());
|
|
||||||
this.dragRulerRanges = undefined;
|
|
||||||
cancelScheduledMeasurement.call(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
async moveToken(event) {
|
|
||||||
// This function is invoked by left clicking
|
|
||||||
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() {
|
|
||||||
const json = super.toJSON();
|
|
||||||
if (this.draggedEntity) {
|
|
||||||
const isToken = this.draggedEntity instanceof Token;
|
|
||||||
json["draggedEntityIsToken"] = isToken;
|
|
||||||
json["draggedEntity"] = this.draggedEntity.id;
|
|
||||||
}
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
update(data) {
|
|
||||||
// Don't show a GMs drag ruler to non GM players
|
|
||||||
if (data.draggedEntity && this.user.isGM && !game.user.isGM && !game.settings.get(settingsKey, "showGMRulerToPlayers"))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (data.draggedEntity) {
|
|
||||||
if (data.draggedEntityIsToken)
|
|
||||||
this.draggedEntity = canvas.tokens.get(data.draggedEntity);
|
|
||||||
else
|
|
||||||
this.draggedEntity = canvas.templates.get(data.draggedEntity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
super.update(data);
|
clear() {
|
||||||
}
|
super.clear();
|
||||||
|
this.previousWaypoints = [];
|
||||||
measure(destination, options={}) {
|
this.previousLabels.removeChildren().forEach(c => c.destroy());
|
||||||
if (this.isDragRuler) {
|
this.dragRulerRanges = undefined;
|
||||||
return measure.call(this, destination, options);
|
cancelScheduledMeasurement.call(this);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
return super.measure(destination, options);
|
async moveToken(event) {
|
||||||
|
// This function is invoked by left clicking
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
_endMeasurement() {
|
toJSON() {
|
||||||
super._endMeasurement();
|
const json = super.toJSON();
|
||||||
this.draggedEntity = null;
|
if (this.draggedEntity) {
|
||||||
}
|
const isToken = this.draggedEntity instanceof Token;
|
||||||
|
json["draggedEntityIsToken"] = isToken;
|
||||||
// The functions below aren't present in the orignal Ruler class and are added by Drag Ruler
|
json["draggedEntity"] = this.draggedEntity.id;
|
||||||
dragRulerAddWaypoint(point, options={}) {
|
}
|
||||||
options.snap = options.snap ?? true;
|
return json;
|
||||||
if (options.snap) {
|
|
||||||
point = getSnapPointForEntity(point.x, point.y, this.draggedEntity);
|
|
||||||
}
|
}
|
||||||
this.waypoints.push(new PIXI.Point(point.x, point.y));
|
|
||||||
this.labels.addChild(new PreciseText("", CONFIG.canvasTextStyle));
|
|
||||||
}
|
|
||||||
|
|
||||||
dragRulerAddWaypointHistory(waypoints) {
|
update(data) {
|
||||||
waypoints.forEach(waypoint => waypoint.isPrevious = true);
|
// Don't show a GMs drag ruler to non GM players
|
||||||
this.waypoints = this.waypoints.concat(waypoints);
|
if (data.draggedEntity && this.user.isGM && !game.user.isGM && !game.settings.get(settingsKey, "showGMRulerToPlayers"))
|
||||||
for (const waypoint of waypoints) {
|
return;
|
||||||
|
|
||||||
|
if (data.draggedEntity) {
|
||||||
|
if (data.draggedEntityIsToken)
|
||||||
|
this.draggedEntity = canvas.tokens.get(data.draggedEntity);
|
||||||
|
else
|
||||||
|
this.draggedEntity = canvas.templates.get(data.draggedEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
super.update(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
measure(destination, options={}) {
|
||||||
|
if (this.isDragRuler) {
|
||||||
|
return measure.call(this, destination, options);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return super.measure(destination, options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_endMeasurement() {
|
||||||
|
super._endMeasurement();
|
||||||
|
this.draggedEntity = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The functions below aren't present in the orignal Ruler class and are added by Drag Ruler
|
||||||
|
dragRulerAddWaypoint(point, options={}) {
|
||||||
|
options.snap = options.snap ?? true;
|
||||||
|
if (options.snap) {
|
||||||
|
point = getSnapPointForEntity(point.x, point.y, this.draggedEntity);
|
||||||
|
}
|
||||||
|
this.waypoints.push(new PIXI.Point(point.x, point.y));
|
||||||
this.labels.addChild(new PreciseText("", CONFIG.canvasTextStyle));
|
this.labels.addChild(new PreciseText("", CONFIG.canvasTextStyle));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
dragRulerClearWaypoints() {
|
dragRulerAddWaypointHistory(waypoints) {
|
||||||
this.waypoints = [];
|
waypoints.forEach(waypoint => waypoint.isPrevious = true);
|
||||||
this.labels.removeChildren().forEach(c => c.destroy());
|
this.waypoints = this.waypoints.concat(waypoints);
|
||||||
}
|
for (const waypoint of waypoints) {
|
||||||
|
this.labels.addChild(new PreciseText("", CONFIG.canvasTextStyle));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dragRulerDeleteWaypoint(event={preventDefault: () => {return}}, options={}) {
|
dragRulerClearWaypoints() {
|
||||||
options.snap = options.snap ?? true;
|
this.waypoints = [];
|
||||||
if (this.waypoints.filter(w => !w.isPrevious).length > 1) {
|
this.labels.removeChildren().forEach(c => c.destroy());
|
||||||
event.preventDefault();
|
}
|
||||||
const mousePosition = canvas.app.renderer.plugins.interaction.mouse.getLocalPosition(canvas.tokens);
|
|
||||||
const rulerOffset = this.rulerOffset;
|
|
||||||
|
|
||||||
// Options are not passed to _removeWaypoint in vanilla Foundry.
|
dragRulerDeleteWaypoint(event={preventDefault: () => {return}}, options={}) {
|
||||||
// Send them in case other modules have overriden that behavior and accept an options parameter (Toggle Snap to Grid)
|
options.snap = options.snap ?? true;
|
||||||
this._removeWaypoint({x: mousePosition.x + rulerOffset.x, y: mousePosition.y + rulerOffset.y}, options);
|
if (this.waypoints.filter(w => !w.isPrevious).length > 1) {
|
||||||
|
event.preventDefault();
|
||||||
|
const mousePosition = canvas.app.renderer.plugins.interaction.mouse.getLocalPosition(canvas.tokens);
|
||||||
|
const rulerOffset = this.rulerOffset;
|
||||||
|
|
||||||
|
// Options are not passed to _removeWaypoint in vanilla Foundry.
|
||||||
|
// Send them in case other modules have overriden that behavior and accept an options parameter (Toggle Snap to Grid)
|
||||||
|
this._removeWaypoint({x: mousePosition.x + rulerOffset.x, y: mousePosition.y + rulerOffset.y}, options);
|
||||||
|
game.user.broadcastActivity({ruler: this});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.dragRulerAbortDrag(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dragRulerAbortDrag(event={preventDefault: () => {return}}) {
|
||||||
|
const token = this.draggedEntity;
|
||||||
|
this._endMeasurement();
|
||||||
|
|
||||||
|
// Deactivate the drag workflow in mouse
|
||||||
|
token.mouseInteractionManager._deactivateDragEvents();
|
||||||
|
token.mouseInteractionManager.state = token.mouseInteractionManager.states.HOVER;
|
||||||
|
|
||||||
|
// This will cancel the current drag operation
|
||||||
|
// Pass in a fake event that hopefully is enough to allow other modules to function
|
||||||
|
token._onDragLeftCancel(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
async dragRulerRecalculate(tokenIds) {
|
||||||
|
if (this._state !== Ruler.STATES.MEASURING)
|
||||||
|
return;
|
||||||
|
if (tokenIds && !tokenIds.includes(this.draggedEntity.id))
|
||||||
|
return;
|
||||||
|
const waypoints = this.waypoints.filter(waypoint => !waypoint.isPrevious);
|
||||||
|
this.dragRulerClearWaypoints();
|
||||||
|
if (game.settings.get(settingsKey, "enableMovementHistory"))
|
||||||
|
this.dragRulerAddWaypointHistory(getMovementHistory(this.draggedEntity));
|
||||||
|
for (const waypoint of waypoints) {
|
||||||
|
this.dragRulerAddWaypoint(waypoint, {snap: false});
|
||||||
|
}
|
||||||
|
this.measure(this.destination);
|
||||||
game.user.broadcastActivity({ruler: this});
|
game.user.broadcastActivity({ruler: this});
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
this.dragRulerAbortDrag(event);
|
static dragRulerGetRaysFromWaypoints(waypoints, destination) {
|
||||||
|
if ( destination )
|
||||||
|
waypoints = waypoints.concat([destination]);
|
||||||
|
return waypoints.slice(1).map((wp, i) => {
|
||||||
|
const ray = new Ray(waypoints[i], wp);
|
||||||
|
ray.isPrevious = Boolean(waypoints[i].isPrevious);
|
||||||
|
return ray;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
dragRulerAbortDrag(event={preventDefault: () => {return}}) {
|
dragRulerGetColorForDistance(distance) {
|
||||||
const token = this.draggedEntity;
|
if (!this.isDragRuler)
|
||||||
this._endMeasurement();
|
|
||||||
|
|
||||||
// Deactivate the drag workflow in mouse
|
|
||||||
token.mouseInteractionManager._deactivateDragEvents();
|
|
||||||
token.mouseInteractionManager.state = token.mouseInteractionManager.states.HOVER;
|
|
||||||
|
|
||||||
// This will cancel the current drag operation
|
|
||||||
// Pass in a fake event that hopefully is enough to allow other modules to function
|
|
||||||
token._onDragLeftCancel(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
async dragRulerRecalculate(tokenIds) {
|
|
||||||
if (this._state !== Ruler.STATES.MEASURING)
|
|
||||||
return;
|
|
||||||
if (tokenIds && !tokenIds.includes(this.draggedEntity.id))
|
|
||||||
return;
|
|
||||||
const waypoints = this.waypoints.filter(waypoint => !waypoint.isPrevious);
|
|
||||||
this.dragRulerClearWaypoints();
|
|
||||||
if (game.settings.get(settingsKey, "enableMovementHistory"))
|
|
||||||
this.dragRulerAddWaypointHistory(getMovementHistory(this.draggedEntity));
|
|
||||||
for (const waypoint of waypoints) {
|
|
||||||
this.dragRulerAddWaypoint(waypoint, {snap: false});
|
|
||||||
}
|
|
||||||
this.measure(this.destination);
|
|
||||||
game.user.broadcastActivity({ruler: this});
|
|
||||||
}
|
|
||||||
|
|
||||||
static dragRulerGetRaysFromWaypoints(waypoints, destination) {
|
|
||||||
if ( destination )
|
|
||||||
waypoints = waypoints.concat([destination]);
|
|
||||||
return waypoints.slice(1).map((wp, i) => {
|
|
||||||
const ray = new Ray(waypoints[i], wp);
|
|
||||||
ray.isPrevious = Boolean(waypoints[i].isPrevious);
|
|
||||||
return ray;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
dragRulerGetColorForDistance(distance) {
|
|
||||||
if (!this.isDragRuler)
|
|
||||||
return this.color;
|
|
||||||
if (!this.draggedEntity.actor) {
|
|
||||||
return this.color;
|
|
||||||
}
|
|
||||||
// Don't apply colors if the current user doesn't have at least observer permissions
|
|
||||||
if (this.draggedEntity.actor.permission < 2) {
|
|
||||||
// If this is a pc and alwaysShowSpeedForPCs is enabled we show the color anyway
|
|
||||||
if (!(this.draggedEntity.actor.data.type === "character" && game.settings.get(settingsKey, "alwaysShowSpeedForPCs")))
|
|
||||||
return this.color;
|
return this.color;
|
||||||
|
if (!this.draggedEntity.actor) {
|
||||||
|
return this.color;
|
||||||
|
}
|
||||||
|
// Don't apply colors if the current user doesn't have at least observer permissions
|
||||||
|
if (this.draggedEntity.actor.permission < 2) {
|
||||||
|
// If this is a pc and alwaysShowSpeedForPCs is enabled we show the color anyway
|
||||||
|
if (!(this.draggedEntity.actor.data.type === "character" && game.settings.get(settingsKey, "alwaysShowSpeedForPCs")))
|
||||||
|
return this.color;
|
||||||
|
}
|
||||||
|
distance = Math.round(distance * 100) / 100;
|
||||||
|
if (!this.dragRulerRanges)
|
||||||
|
this.dragRulerRanges = getRangesFromSpeedProvider(this.draggedEntity);
|
||||||
|
return getColorForDistanceAndToken(distance, this.draggedEntity, this.dragRulerRanges) ?? this.color;
|
||||||
}
|
}
|
||||||
distance = Math.round(distance * 100) / 100;
|
|
||||||
if (!this.dragRulerRanges)
|
|
||||||
this.dragRulerRanges = getRangesFromSpeedProvider(this.draggedEntity);
|
|
||||||
return getColorForDistanceAndToken(distance, this.draggedEntity, this.dragRulerRanges) ?? this.color;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ruler = DragRulerRuler;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user