From 50a307b271e78f425f073c5c610a7de7cca6dbf0 Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Thu, 25 Dec 2025 02:12:36 +0100 Subject: [PATCH] [Feature] TokenConfig Actor Size Edit (#1470) * Added the select and handliing * Fixed so tokenPreview works with tokenSize * Correction for prototypeToken * Extracted common logic to token-config-mixin.mjs * Update templates/sheets-settings/token-config/appearance.hbs Co-authored-by: Carlos Fernandez --------- Co-authored-by: Carlos Fernandez --- .../sheets-configs/prototype-token-config.mjs | 59 ++++----- .../sheets-configs/token-config-mixin.mjs | 114 ++++++++++++++++++ .../sheets-configs/token-config.mjs | 44 ++----- .../token-config/appearance.hbs | 35 ++++-- 4 files changed, 167 insertions(+), 85 deletions(-) create mode 100644 module/applications/sheets-configs/token-config-mixin.mjs diff --git a/module/applications/sheets-configs/prototype-token-config.mjs b/module/applications/sheets-configs/prototype-token-config.mjs index 0bb9703a..9faf6e71 100644 --- a/module/applications/sheets-configs/prototype-token-config.mjs +++ b/module/applications/sheets-configs/prototype-token-config.mjs @@ -1,41 +1,30 @@ -export default class DhPrototypeTokenConfig extends foundry.applications.sheets.PrototypeTokenConfig { - /** @override */ - static PARTS = { - tabs: super.PARTS.tabs, - identity: super.PARTS.identity, - appearance: { - template: 'systems/daggerheart/templates/sheets-settings/token-config/appearance.hbs', - scrollable: [''] - }, - vision: super.PARTS.vision, - light: super.PARTS.light, - resources: super.PARTS.resources, - footer: super.PARTS.footer +import DHTokenConfigMixin from './token-config-mixin.mjs'; +import { getActorSizeFromForm } from './token-config-mixin.mjs'; + +export default class DhPrototypeTokenConfig extends DHTokenConfigMixin( + foundry.applications.sheets.PrototypeTokenConfig +) { + /** @inheritDoc */ + static DEFAULT_OPTIONS = { + ...super.DEFAULT_OPTIONS, + form: { handler: DhPrototypeTokenConfig.#onSubmit } }; - /** @inheritDoc */ - async _prepareResourcesTab() { - const token = this.token; - const usesTrackableAttributes = !foundry.utils.isEmpty(CONFIG.Actor.trackableAttributes); - const attributeSource = - this.actor?.system instanceof foundry.abstract.DataModel && usesTrackableAttributes - ? this.actor?.type - : this.actor?.system; - const TokenDocument = foundry.utils.getDocumentClass('Token'); - const attributes = TokenDocument.getTrackedAttributes(attributeSource); - return { - barAttributes: TokenDocument.getTrackedAttributeChoices(attributes, attributeSource), - bar1: token.getBarAttribute?.('bar1'), - bar2: token.getBarAttribute?.('bar2'), - turnMarkerModes: DhPrototypeTokenConfig.TURN_MARKER_MODES, - turnMarkerAnimations: CONFIG.Combat.settings.turnMarkerAnimations - }; - } + /** + * Process form submission for the sheet + * @this {PrototypeTokenConfig} + * @type {ApplicationFormSubmission} + */ + static async #onSubmit(event, form, formData) { + const submitData = this._processFormData(event, form, formData); + submitData.detectionModes ??= []; // Clear detection modes array + this._processChanges(submitData); + const changes = { prototypeToken: submitData }; - async _prepareAppearanceTab() { - const context = await super._prepareAppearanceTab(); - context.actorSizeUsed = this.token.actor ? Boolean(this.token.actor.system.size) : false; + const changedTokenSizeValue = getActorSizeFromForm(this.element, this.actor); + if (changedTokenSizeValue) changes.system = { size: changedTokenSizeValue }; - return context; + this.actor.validate({ changes, clean: true, fallback: false }); + await this.actor.update(changes); } } diff --git a/module/applications/sheets-configs/token-config-mixin.mjs b/module/applications/sheets-configs/token-config-mixin.mjs new file mode 100644 index 00000000..c29b54ff --- /dev/null +++ b/module/applications/sheets-configs/token-config-mixin.mjs @@ -0,0 +1,114 @@ +export default function DHTokenConfigMixin(Base) { + class DHTokenConfigBase extends Base { + /** @override */ + static PARTS = { + tabs: super.PARTS.tabs, + identity: super.PARTS.identity, + appearance: { + template: 'systems/daggerheart/templates/sheets-settings/token-config/appearance.hbs', + scrollable: [''] + }, + vision: super.PARTS.vision, + light: super.PARTS.light, + resources: super.PARTS.resources, + footer: super.PARTS.footer + }; + + _attachPartListeners(partId, htmlElement, options) { + super._attachPartListeners(partId, htmlElement, options); + + switch (partId) { + case 'appearance': + htmlElement + .querySelector('#dhTokenSize') + ?.addEventListener('change', this.onTokenSizeChange.bind(this)); + break; + } + } + + /** @inheritDoc */ + async _prepareResourcesTab() { + const token = this.token; + const usesTrackableAttributes = !foundry.utils.isEmpty(CONFIG.Actor.trackableAttributes); + const attributeSource = + this.actor?.system instanceof foundry.abstract.DataModel && usesTrackableAttributes + ? this.actor?.type + : this.actor?.system; + const TokenDocument = foundry.utils.getDocumentClass('Token'); + const attributes = TokenDocument.getTrackedAttributes(attributeSource); + return { + barAttributes: TokenDocument.getTrackedAttributeChoices(attributes, attributeSource), + bar1: token.getBarAttribute?.('bar1'), + bar2: token.getBarAttribute?.('bar2'), + turnMarkerModes: DHTokenConfigBase.TURN_MARKER_MODES, + turnMarkerAnimations: CONFIG.Combat.settings.turnMarkerAnimations + }; + } + + async _prepareAppearanceTab() { + const context = await super._prepareAppearanceTab(); + context.tokenSizes = CONFIG.DH.ACTOR.tokenSize; + context.tokenSize = this.actor?.system?.size; + context.usesActorSize = this.actor?.system?.metadata?.usesSize; + context.actorSizeDisable = context.usesActorSize && this.actor.system.size !== 'custom'; + + return context; + } + + /** @inheritDoc */ + _previewChanges(changes) { + if (!changes || !this._preview) return; + + const tokenSizeSelect = this.element?.querySelector('#dhTokenSize'); + if (this.actor && tokenSizeSelect && tokenSizeSelect.value !== 'custom') { + const tokenSizes = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).tokenSizes; + const tokenSize = tokenSizes[tokenSizeSelect.value]; + changes.width = tokenSize; + changes.height = tokenSize; + } + + const deletions = { '-=actorId': null, '-=actorLink': null }; + const mergeOptions = { inplace: false, performDeletions: true }; + this._preview.updateSource(mergeObject(changes, deletions, mergeOptions)); + + if (this._preview?.object?.destroyed === false) { + this._preview.object.initializeSources(); + this._preview.object.renderFlags.set({ refresh: true }); + } + } + + async onTokenSizeChange(event) { + const value = event.target.value; + const tokenSizeDimensions = this.element.querySelector('#tokenSizeDimensions'); + if (tokenSizeDimensions) { + const disabled = value !== 'custom'; + + tokenSizeDimensions.dataset.tooltip = disabled + ? game.i18n.localize('DAGGERHEART.APPLICATIONS.TokenConfig.actorSizeUsed') + : ''; + + const disabledIcon = tokenSizeDimensions.querySelector('i'); + if (disabledIcon) { + disabledIcon.style.opacity = disabled ? '' : '0'; + } + + const dimensionsInputs = tokenSizeDimensions.querySelectorAll('.form-fields input'); + for (const input of dimensionsInputs) { + input.disabled = disabled; + } + } + } + } + + return DHTokenConfigBase; +} + +export function getActorSizeFromForm(element, actor) { + const tokenSizeSelect = element.querySelector('#dhTokenSize'); + const isSizeDifferent = tokenSizeSelect?.value !== actor?.system?.size; + if (tokenSizeSelect && actor && isSizeDifferent) { + return tokenSizeSelect.value; + } + + return null; +} diff --git a/module/applications/sheets-configs/token-config.mjs b/module/applications/sheets-configs/token-config.mjs index 5f4e4f56..d7450bd6 100644 --- a/module/applications/sheets-configs/token-config.mjs +++ b/module/applications/sheets-configs/token-config.mjs @@ -1,41 +1,11 @@ -export default class DhTokenConfig extends foundry.applications.sheets.TokenConfig { - /** @override */ - static PARTS = { - tabs: super.PARTS.tabs, - identity: super.PARTS.identity, - appearance: { - template: 'systems/daggerheart/templates/sheets-settings/token-config/appearance.hbs', - scrollable: [''] - }, - vision: super.PARTS.vision, - light: super.PARTS.light, - resources: super.PARTS.resources, - footer: super.PARTS.footer - }; +import DHTokenConfigMixin from './token-config-mixin.mjs'; +import { getActorSizeFromForm } from './token-config-mixin.mjs'; - /** @inheritDoc */ - async _prepareResourcesTab() { - const token = this.token; - const usesTrackableAttributes = !foundry.utils.isEmpty(CONFIG.Actor.trackableAttributes); - const attributeSource = - this.actor?.system instanceof foundry.abstract.DataModel && usesTrackableAttributes - ? this.actor?.type - : this.actor?.system; - const TokenDocument = foundry.utils.getDocumentClass('Token'); - const attributes = TokenDocument.getTrackedAttributes(attributeSource); - return { - barAttributes: TokenDocument.getTrackedAttributeChoices(attributes, attributeSource), - bar1: token.getBarAttribute?.('bar1'), - bar2: token.getBarAttribute?.('bar2'), - turnMarkerModes: DhTokenConfig.TURN_MARKER_MODES, - turnMarkerAnimations: CONFIG.Combat.settings.turnMarkerAnimations - }; - } +export default class DhTokenConfig extends DHTokenConfigMixin(foundry.applications.sheets.TokenConfig) { + async _processSubmitData(event, form, submitData, options) { + const changedTokenSizeValue = getActorSizeFromForm(this.element, this.actor); + if (changedTokenSizeValue) this.token.actor.update({ 'system.size': changedTokenSizeValue }); - async _prepareAppearanceTab() { - const context = await super._prepareAppearanceTab(); - context.actorSizeUsed = this.token.actor ? Boolean(this.token.actor.system.size) : false; - - return context; + super._processSubmitData(event, form, submitData, options); } } diff --git a/templates/sheets-settings/token-config/appearance.hbs b/templates/sheets-settings/token-config/appearance.hbs index 0f6019ba..abdb49c2 100644 --- a/templates/sheets-settings/token-config/appearance.hbs +++ b/templates/sheets-settings/token-config/appearance.hbs @@ -10,22 +10,31 @@ {{/if}} +
+ {{localize "Token Size"}} + {{#if usesActorSize}} +
+ + +
+ {{/if}} -
- -
- - {{formInput fields.width value=source.width id=(concat rootId "-width") disabled=actorSizeUsed}} - - {{formInput fields.height value=source.height id=(concat rootId "-height") disabled=actorSizeUsed}} +
+ +
+ + {{formInput fields.width value=source.width id=(concat rootId "-width") disabled=actorSizeDisable}} + + {{formInput fields.height value=source.height id=(concat rootId "-height") disabled=actorSizeDisable}} +
-
+
{{#if shapes}} {{formGroup fields.shape value=source.shape choices=shapes classes="slim" rootId=rootId}}