|
|
- import { TVA_CONFIG } from '../settings.js';
- import { decodeURISafely } from '../utils.js';
- import { registerWrapper } from './wrappers.js';
-
- const feature_id = 'UserMappings';
-
- export function registerUserMappingWrappers() {
- registerWrapper(feature_id, 'Tile.prototype.draw', _draw);
- registerWrapper(feature_id, 'Token.prototype.draw', _draw);
- }
-
- async function _draw(wrapped, ...args) {
- let result;
-
- // If the Token/Tile has a UserToImage mappings momentarily set document.texture.src to it
- // so that it's texture gets loaded instead of the actual Token image
- const mappings = this.document.getFlag('token-variants', 'userMappings') || {};
- const img = mappings[game.userId];
- let previous;
- if (img) {
- previous = this.document.texture.src;
- this.document.texture.src = img;
- this.tva_iconOverride = img;
- result = await wrapped(...args);
- this.document.texture.src = previous;
- overrideVisibility(this, img);
- } else {
- overrideVisibility(this);
- result = await wrapped(...args);
- }
-
- return result;
- }
-
- /**
- * If the img is the same as TVA_CONFIG.invisibleImage then we'll override the isVisible
- * getter to return false of this client if it's not a GM. Reset it to default if not.
- * @param {*} obj object whose isVisible is to be overriden
- * @param {*} img UserToImage mapping
- */
- function overrideVisibility(obj, img) {
- if (img && decodeURISafely(img) === TVA_CONFIG.invisibleImage && !obj.tva_customVisibility) {
- const originalIsVisible = _getIsVisibleDescriptor(obj).get;
- Object.defineProperty(obj, 'isVisible', {
- get: function () {
- const isVisible = originalIsVisible.call(this);
- if (isVisible && !game.user.isGM) return false;
- return isVisible;
- },
- configurable: true,
- });
- obj.tva_customVisibility = true;
- } else if (!img && obj.tva_customVisibility) {
- Object.defineProperty(obj, 'isVisible', _getIsVisibleDescriptor(obj));
- delete obj.tva_customVisibility;
- }
- }
-
- function _getIsVisibleDescriptor(obj) {
- let iObj = Object.getPrototypeOf(obj);
- let descriptor = null;
- while (iObj) {
- descriptor = Object.getOwnPropertyDescriptor(iObj, 'isVisible');
- if (descriptor) break;
- iObj = Object.getPrototypeOf(iObj);
- }
- return descriptor;
- }
-
- /**
- * Assign an image to be displayed to only that user.
- * @param {*} token token the image is to be applied to
- * @param {*} img image to be displayed, if no image is provided unassignUserSpecificImage(...) will be called
- * @param {*} opts.userName name of the user that the image is to be displayed to
- * @param {*} opts.id id of the user that the image is to be displayed to
- * @returns
- */
- export function assignUserSpecificImage(token, img, { userName = null, userId = null } = {}) {
- if (!img) return unassignUserSpecificImage(token, { userName, userId });
-
- if (userName instanceof Array) {
- for (const name of userName) assignUserSpecificImage(token, img, { userName: name });
- return;
- }
-
- if (userId instanceof Array) {
- for (const id of userId) assignUserSpecificImage(token, img, { userId: id });
- return;
- }
-
- let id = userId;
- if (!id && userName) {
- id = game.users.find((u) => u.name === userName)?.id;
- }
- if (!id) return;
-
- const doc = token.document ?? token;
- const mappings = doc.getFlag('token-variants', 'userMappings') || {};
-
- mappings[id] = img;
- doc.setFlag('token-variants', 'userMappings', mappings);
- }
-
- /**
- * Calls assignUserSpecificImage passing in all currently selected tokens.
- * @param {*} img image to be displayed
- * @param {*} opts id or name of the user as per assignUserSpecificImage(...)
- */
- export function assignUserSpecificImageToSelected(img, opts = {}) {
- const selected = [...canvas.tokens.controlled];
- for (const t of selected) assignUserSpecificImage(t, img, opts);
- }
-
- /**
- * Un-assign image if one has been set to be displayed to a user.
- * @param {*} token token the image is to be removed from
- * @param {*} opts.userName name of the user that the image is to be removed for
- * @param {*} opts.id id of the user that the image is to be removed for
- */
- export function unassignUserSpecificImage(token, { userName = null, userId = null } = {}) {
- if (userName instanceof Array) {
- for (const name of userName) unassignUserSpecificImage(token, { userName: name });
- return;
- }
-
- if (userId instanceof Array) {
- for (const id of userId) unassignUserSpecificImage(token, { userId: id });
- return;
- }
-
- let id = userId;
- if (!id && userName) {
- id = game.users.find((u) => u.name === userName)?.id;
- }
- if (!id) {
- if (!userName && !userId) (token.document ?? token).unsetFlag('token-variants', 'userMappings');
- } else {
- const update = {};
- update['flags.token-variants.userMappings.-=' + id] = null;
- (token.document ?? token).update(update);
- }
- }
-
- /**
- * Calls unassignUserSpecificImage passing in all currently selected tokens.
- * @param {*} opts id or name of the user as per unassignUserSpecificImage(...)
- */
- export function unassignUserSpecificImageFromSelected(opts = {}) {
- const selected = [...canvas.tokens.controlled];
- for (const t of selected) unassignUserSpecificImage(t, opts);
- }
|