Skip to content

Commit

Permalink
💄 style|Token|Reorganize the Token file
Browse files Browse the repository at this point in the history
  • Loading branch information
caewok committed Jul 11, 2024
1 parent 86dc44d commit 8fcdaaf
Showing 1 changed file with 70 additions and 51 deletions.
121 changes: 70 additions & 51 deletions scripts/Token.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,40 @@ PATCHES.TOKEN_RULER = {}; // Assume this patch is only present if the token rule
PATCHES.MOVEMENT_TRACKING = {};
PATCHES.PATHFINDING = {};

// ----- NOTE: Hooks ----- //

/**
* Hook updateToken to track token movement.
* @param {Document} document The existing Document which was updated
* @param {object} change Differential data that was used to update the document
* @param {DocumentModificationContext} options Additional options which modified the update request
* @param {string} userId The ID of the User who triggered the update workflow
*/
function updateToken(document, changes, _options, _userId) {
const token = document.object;
if ( token.isPreview
|| !(Object.hasOwn(changes, "x")|| Object.hasOwn(changes, "y") || Object.hasOwn(changes, "elevation")) ) return;

const ruler = canvas.controls.ruler;
if ( ruler.active && ruler.token === token ) token._lastMoveDistance = ruler.totalMoveDistance;
else token._lastMoveDistance = Ruler.measureMoveDistance(token.position, token.document._source, { token }).moveDistance;
if ( game.combat?.started ) {
// Store the combat move distance and the last round for which the combat move occurred.
// Map to each unique combat.
const combatId = game.combat.id;
token._combatMoveData ??= new Map();
if ( !token._combatMoveData.has(combatId) ) {
token._combatMoveData.set(combatId, { lastMoveDistance: 0, lastRound: -1 });
}
const combatData = token._combatMoveData.get(combatId);
if ( combatData.lastRound < game.combat.round ) combatData.lastMoveDistance = token._lastMoveDistance;
else combatData.lastMoveDistance += token._lastMoveDistance;
combatData.lastRound = game.combat.round;
}
}

// ----- NOTE: Wraps ----- //

/**
* Wrap Token.prototype._onDragLeftStart
* Start a ruler measurement.
Expand Down Expand Up @@ -67,6 +101,18 @@ function _onDragLeftMove(wrapped, event) {
if ( ruler._state > 0 ) ruler._onMouseMove(event);
}

/**
* Wrap Token.prototype._onUpdate to remove easing for pathfinding segments.
*/
function _onUpdate(wrapped, data, options, userId) {
if ( options?.rulerSegment && options?.animation?.easing ) {
options.animation.easing = options.firstRulerSegment ? noEndEase(options.animation.easing)
: options.lastRulerSegment ? noStartEase(options.animation.easing)
: undefined;
}
return wrapped(data, options, userId);
}

/**
* Mix Token.prototype._onDragLeftDrop
* End the ruler measurement.
Expand All @@ -87,6 +133,8 @@ async function _onDragLeftDrop(wrapped, event) {
ruler._onMoveKeyDown(event); // Movement is async here but not awaited in _onMoveKeyDown.
}

// ----- NOTE: New getters ----- //

/**
* Token.prototype.lastMoveDistance
* Return the last move distance. If combat is active, return the last move since this token
Expand All @@ -103,57 +151,7 @@ function lastMoveDistance() {
return this._lastMoveDistance || 0;
}

/**
* Hook updateToken to track token movement.
* @param {Document} document The existing Document which was updated
* @param {object} change Differential data that was used to update the document
* @param {DocumentModificationContext} options Additional options which modified the update request
* @param {string} userId The ID of the User who triggered the update workflow
*/
function updateToken(document, changes, _options, _userId) {
const token = document.object;
if ( token.isPreview
|| !(Object.hasOwn(changes, "x")|| Object.hasOwn(changes, "y") || Object.hasOwn(changes, "elevation")) ) return;

const ruler = canvas.controls.ruler;
if ( ruler.active && ruler.token === token ) token._lastMoveDistance = ruler.totalMoveDistance;
else token._lastMoveDistance = Ruler.measureMoveDistance(token.position, token.document._source, { token }).moveDistance;
if ( game.combat?.started ) {
// Store the combat move distance and the last round for which the combat move occurred.
// Map to each unique combat.
const combatId = game.combat.id;
token._combatMoveData ??= new Map();
if ( !token._combatMoveData.has(combatId) ) {
token._combatMoveData.set(combatId, { lastMoveDistance: 0, lastRound: -1 });
}
const combatData = token._combatMoveData.get(combatId);
if ( combatData.lastRound < game.combat.round ) combatData.lastMoveDistance = token._lastMoveDistance;
else combatData.lastMoveDistance += token._lastMoveDistance;
combatData.lastRound = game.combat.round;
}
}

/**
* Wrap Token.prototype._onUpdate to remove easing for pathfinding segments.
*/
function _onUpdate(wrapped, data, options, userId) {
if ( options?.rulerSegment && options?.animation?.easing ) {
options.animation.easing = options.firstRulerSegment ? noEndEase(options.animation.easing)
: options.lastRulerSegment ? noStartEase(options.animation.easing)
: undefined;
}
return wrapped(data, options, userId);
}

function noStartEase(easing) {
if ( typeof easing === "string" ) easing = CanvasAnimation[easing];
return pt => (pt < 0.5) ? pt : easing(pt);
}

function noEndEase(easing) {
if ( typeof easing === "string" ) easing = CanvasAnimation[easing];
return pt => (pt > 0.5) ? pt : easing(pt);
}
// ----- NOTE: Patches ----- //

PATCHES.TOKEN_RULER.WRAPS = {
_onDragLeftStart,
Expand All @@ -167,3 +165,24 @@ PATCHES.TOKEN_RULER.MIXES = { _onDragLeftDrop, _onDragLeftCancel };
PATCHES.MOVEMENT_TRACKING.HOOKS = { updateToken };
PATCHES.MOVEMENT_TRACKING.GETTERS = { lastMoveDistance };

// ----- NOTE: Helper functions ----- //

/**
* For given easing function, modify it so it does not ease for the first half of the move.
* @param {function} easing
* @returns {function}
*/
function noStartEase(easing) {
if ( typeof easing === "string" ) easing = CanvasAnimation[easing];
return pt => (pt < 0.5) ? pt : easing(pt);
}

/**
* For given easing function, modify it so it does not ease for the second half of the move.
* @param {function} easing
* @returns {function}
*/
function noEndEase(easing) {
if ( typeof easing === "string" ) easing = CanvasAnimation[easing];
return pt => (pt > 0.5) ? pt : easing(pt);
}

0 comments on commit 8fcdaaf

Please sign in to comment.