Port to libwrapper
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
}
|
||||
],
|
||||
"esmodules": [
|
||||
"src/libwrapper_shim.js",
|
||||
"src/main.js",
|
||||
"src/socket.js"
|
||||
],
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright © 2021 fvtt-lib-wrapper Rui Pinheiro
|
||||
|
||||
|
||||
'use strict';
|
||||
|
||||
// A shim for the libWrapper library
|
||||
export let libWrapper = undefined;
|
||||
|
||||
export const VERSIONS = [1,11,0];
|
||||
export const TGT_SPLIT_RE = new RegExp("([^.[]+|\\[('([^'\\\\]|\\\\.)+?'|\"([^\"\\\\]|\\\\.)+?\")\\])", 'g');
|
||||
export const TGT_CLEANUP_RE = new RegExp("(^\\['|'\\]$|^\\[\"|\"\\]$)", 'g');
|
||||
|
||||
// Main shim code
|
||||
Hooks.once('init', () => {
|
||||
// Check if the real module is already loaded - if so, use it
|
||||
if(globalThis.libWrapper && !(globalThis.libWrapper.is_fallback ?? true)) {
|
||||
libWrapper = globalThis.libWrapper;
|
||||
return;
|
||||
}
|
||||
|
||||
// Fallback implementation
|
||||
libWrapper = class {
|
||||
static get is_fallback() { return true };
|
||||
|
||||
static get WRAPPER() { return 'WRAPPER' };
|
||||
static get MIXED() { return 'MIXED' };
|
||||
static get OVERRIDE() { return 'OVERRIDE' };
|
||||
|
||||
static register(package_id, target, fn, type="MIXED", {chain=undefined}={}) {
|
||||
const is_setter = target.endsWith('#set');
|
||||
target = !is_setter ? target : target.slice(0, -4);
|
||||
const split = target.match(TGT_SPLIT_RE).map((x)=>x.replace(/\\(.)/g, '$1').replace(TGT_CLEANUP_RE,''));
|
||||
const root_nm = split.splice(0,1)[0];
|
||||
|
||||
let obj, fn_name;
|
||||
if(split.length == 0) {
|
||||
obj = globalThis;
|
||||
fn_name = root_nm;
|
||||
}
|
||||
else {
|
||||
const _eval = eval;
|
||||
fn_name = split.pop();
|
||||
obj = split.reduce((x,y)=>x[y], globalThis[root_nm] ?? _eval(root_nm));
|
||||
}
|
||||
|
||||
let iObj = obj;
|
||||
let descriptor = null;
|
||||
while(iObj) {
|
||||
descriptor = Object.getOwnPropertyDescriptor(iObj, fn_name);
|
||||
if(descriptor) break;
|
||||
iObj = Object.getPrototypeOf(iObj);
|
||||
}
|
||||
if(!descriptor || descriptor?.configurable === false) throw `libWrapper Shim: '${target}' does not exist, could not be found, or has a non-configurable descriptor.`;
|
||||
|
||||
let original = null;
|
||||
const wrapper = (chain ?? (type.toUpperCase?.() != 'OVERRIDE' && type != 3)) ? function() { return fn.call(this, original.bind(this), ...arguments); } : function() { return fn.apply(this, arguments); };
|
||||
|
||||
if(!is_setter) {
|
||||
if(descriptor.value) {
|
||||
original = descriptor.value;
|
||||
descriptor.value = wrapper;
|
||||
}
|
||||
else {
|
||||
original = descriptor.get;
|
||||
descriptor.get = wrapper;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(!descriptor.set) throw `libWrapper Shim: '${target}' does not have a setter`;
|
||||
original = descriptor.set;
|
||||
descriptor.set = wrapper;
|
||||
}
|
||||
|
||||
descriptor.configurable = true;
|
||||
Object.defineProperty(obj, fn_name, descriptor);
|
||||
}
|
||||
}
|
||||
});
|
||||
+37
-53
@@ -3,6 +3,7 @@
|
||||
import {currentSpeedProvider, getColorForDistanceAndToken, getMovedDistanceFromToken, getRangesFromSpeedProvider, initApi, registerModule, registerSystem} from "./api.js";
|
||||
import {checkDependencies, getHexSizeSupportTokenGridCenter, highlightMeasurementTerrainRuler} from "./compatibility.js";
|
||||
import {moveEntities, onMouseMove} from "./foundry_imports.js"
|
||||
import {libWrapper} from "./libwrapper_shim.js";
|
||||
import {performMigrations} from "./migration.js"
|
||||
import {getMovementHistory, removeLastHistoryEntryIfAt, resetMovementHistory} from "./movement_tracking.js";
|
||||
import {extendRuler} from "./ruler.js";
|
||||
@@ -16,8 +17,8 @@ Hooks.once("init", () => {
|
||||
initApi()
|
||||
hookDragHandlers(Token);
|
||||
hookDragHandlers(MeasuredTemplate);
|
||||
hookKeyboardManagerFunctions()
|
||||
hookLayerFunctions();
|
||||
libWrapper.register("drag-ruler", "KeyboardManager.prototype._handleKeys", forwardIfUnahndled(handleKeys), "MIXED");
|
||||
libWrapper.register("drag-ruler", "TokenLayer.prototype.undoHistory", tokenLayerUndoHistory, "WRAPPER");
|
||||
|
||||
extendRuler();
|
||||
|
||||
@@ -57,59 +58,35 @@ Hooks.on("getCombatTrackerEntryContext", function (html, menu) {
|
||||
menu.splice(1, 0, entry);
|
||||
});
|
||||
|
||||
function forwardIfUnahndled(newFn) {
|
||||
return function(oldFn, ...args) {
|
||||
const eventHandled = newFn(...args);
|
||||
if (!eventHandled)
|
||||
oldFn(...args);
|
||||
};
|
||||
}
|
||||
|
||||
function hookDragHandlers(entityType) {
|
||||
const originalDragLeftStartHandler = entityType.prototype._onDragLeftStart
|
||||
entityType.prototype._onDragLeftStart = function(event) {
|
||||
originalDragLeftStartHandler.call(this, event)
|
||||
onEntityLeftDragStart.call(this, event)
|
||||
}
|
||||
|
||||
const originalDragLeftMoveHandler = entityType.prototype._onDragLeftMove
|
||||
entityType.prototype._onDragLeftMove = function (event) {
|
||||
if (entityType === Token)
|
||||
applyGridlessSnapping.call(this, event);
|
||||
originalDragLeftMoveHandler.call(this, event)
|
||||
onEntityLeftDragMove.call(this, event)
|
||||
}
|
||||
|
||||
const originalDragLeftDropHandler = entityType.prototype._onDragLeftDrop
|
||||
entityType.prototype._onDragLeftDrop = function (event) {
|
||||
const eventHandled = onEntityDragLeftDrop.call(this, event)
|
||||
if (!eventHandled)
|
||||
originalDragLeftDropHandler.call(this, event)
|
||||
}
|
||||
|
||||
const originalDragLeftCancelHandler = entityType.prototype._onDragLeftCancel
|
||||
entityType.prototype._onDragLeftCancel = function (event) {
|
||||
const eventHandled = onEntityDragLeftCancel.call(this, event)
|
||||
if (!eventHandled)
|
||||
originalDragLeftCancelHandler.call(this, event)
|
||||
}
|
||||
const entityName = entityType.name
|
||||
libWrapper.register("drag-ruler", `${entityName}.prototype._onDragLeftStart`, onEntityLeftDragStart, "WRAPPER");
|
||||
if (entityType === Token)
|
||||
libWrapper.register("drag-ruler", `${entityName}.prototype._onDragLeftMove`, onEntityLeftDragMoveSnap, "WRAPPER");
|
||||
else
|
||||
libWrapper.register("drag-ruler", `${entityName}.prototype._onDragLeftMove`, onEntityLeftDragMove, "WRAPPER");
|
||||
libWrapper.register("drag-ruler", `${entityName}.prototype._onDragLeftDrop`, forwardIfUnahndled(onEntityDragLeftDrop), "MIXED");
|
||||
libWrapper.register("drag-ruler", `${entityName}.prototype._onDragLeftCancel`, forwardIfUnahndled(onEntityDragLeftCancel), "MIXED");
|
||||
}
|
||||
|
||||
function hookKeyboardManagerFunctions() {
|
||||
const originalHandleKeys = KeyboardManager.prototype._handleKeys
|
||||
KeyboardManager.prototype._handleKeys = function (event, key, up) {
|
||||
const eventHandled = handleKeys.call(this, event, key, up)
|
||||
if (!eventHandled)
|
||||
originalHandleKeys.call(this, event, key, up)
|
||||
}
|
||||
}
|
||||
|
||||
function hookLayerFunctions() {
|
||||
const originalTokenLayerUndoHistory = TokenLayer.prototype.undoHistory;
|
||||
TokenLayer.prototype.undoHistory = function () {
|
||||
const historyEntry = this.history[this.history.length - 1];
|
||||
return originalTokenLayerUndoHistory.call(this).then((returnValue) => {
|
||||
if (historyEntry.type === "update") {
|
||||
for (const entry of historyEntry.data) {
|
||||
const token = canvas.tokens.get(entry._id);
|
||||
removeLastHistoryEntryIfAt(token, entry.x, entry.y);
|
||||
}
|
||||
}
|
||||
return returnValue;
|
||||
});
|
||||
async function tokenLayerUndoHistory(wrapped) {
|
||||
const historyEntry = this.history[this.history.length - 1];
|
||||
const returnValue = await wrapped();
|
||||
if (historyEntry.type === "update") {
|
||||
for (const entry of historyEntry.data) {
|
||||
const token = canvas.tokens.get(entry._id);
|
||||
removeLastHistoryEntryIfAt(token, entry.x, entry.y);
|
||||
}
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
function handleKeys(event, key, up) {
|
||||
@@ -180,7 +157,8 @@ function onKeyEscape(up) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function onEntityLeftDragStart(event) {
|
||||
function onEntityLeftDragStart(wrapped, event) {
|
||||
wrapped(event);
|
||||
const isToken = this instanceof Token;
|
||||
const ruler = canvas.controls.ruler
|
||||
ruler.draggedEntity = this;
|
||||
@@ -218,7 +196,13 @@ function startDragRuler(options, measureImmediately=true) {
|
||||
ruler.measure(destination, options);
|
||||
}
|
||||
|
||||
function onEntityLeftDragMove(event) {
|
||||
function onEntityLeftDragMoveSnap(wrapped, event) {
|
||||
applyGridlessSnapping.call(this, event);
|
||||
onEntityLeftDragMove.call(this, wrapped, event);
|
||||
}
|
||||
|
||||
function onEntityLeftDragMove(wrapped, event) {
|
||||
wrapped(event);
|
||||
const ruler = canvas.controls.ruler
|
||||
if (ruler.isDragRuler)
|
||||
onMouseMove.call(ruler, event)
|
||||
|
||||
Reference in New Issue
Block a user