From 14ea993319901286cec1bd9edd50b0f9dba5fb40 Mon Sep 17 00:00:00 2001 From: Peterlankton <61578137+Kapuzenjoe@users.noreply.github.com> Date: Sun, 22 Jun 2025 15:17:46 +0200 Subject: [PATCH 1/7] upgrade presetSelector to DialogV2 --- module.json | 4 +- src/activeLighting.js | 139 ++++++++++++++++++++---------------------- 2 files changed, 69 insertions(+), 74 deletions(-) diff --git a/module.json b/module.json index d6119bb..182e517 100644 --- a/module.json +++ b/module.json @@ -13,8 +13,8 @@ ], "version": "0.6.2", "compatibility": { - "minimum": 11, - "verified": 12 + "minimum": 13, + "verified": 13 }, "esmodules": ["src/activeLighting.js", "src/updateManager.js"], "packs": [ diff --git a/src/activeLighting.js b/src/activeLighting.js index 8c24ab0..1cfc08b 100644 --- a/src/activeLighting.js +++ b/src/activeLighting.js @@ -86,7 +86,7 @@ class ATL { default: "0.2.15", type: String, }); - + } @@ -98,7 +98,7 @@ class ATL { let effects; if (newTransferral) effects = actor.appliedEffects; else if (game.system.id === "wfrp4e") - effects = actor.actorEffects.filter((e) => !e.disabled && !e.isSuppressed); + effects = actor.actorEffects.filter((e) => !e.disabled && !e.isSuppressed); else effects = actor.effects.filter((e) => !e.disabled && !e.isSuppressed); // only return effects that have some ATL changes in them return effects.filter(e => e.changes.some(c => c.key.startsWith("ATL."))); @@ -203,68 +203,63 @@ class ATL { static async UpdatePresets() { let presets = await game.settings.get("ATL", "presets") - let content = `
` - let presetSelector = new Dialog({ - title: "Preset Selector", + let presetSelector = new foundry.applications.api.DialogV2({ + window: { + title: "Preset Selector" + }, content: ` -
- - ${content} -
`, - content, - buttons: { - one: { - label: "Update", - icon: ``, - callback: (html) => { - let updatePreset = html.find("[name=presets]")[0].value; - let preset = presets.find(p => p.id === updatePreset) - new PresetConfig(preset).render(true); - } - }, - two: { - label: "Create Copy", - icon: ``, - callback: (html) => { - let updatePreset = html.find("[name=presets]")[0].value; - let preset = presets.find(p => p.id === updatePreset) - // copy and remove ID so it's created as new - preset = deepClone(preset); - delete preset.id; - new PresetConfig(preset).render(true); - } - }, - three: { - label: "Delete", - icon: ``, - callback: (html) => { - let updatePreset = html.find("[name=presets]")[0].value; - let index = presets.findIndex(p => p.id === updatePreset); - new Dialog({ - title: "Conformation", - content: `Are you sure you want to remove this preset`, - buttons: { - one: { - label: "Confirm", - icon: ``, - callback: () => { - presets.splice(index, 1); - game.settings.set("ATL", "presets", presets); - } - }, - two: { - label: "Return", - icon: ``, - callback: () => presetSelector.render(true) - } - } - }).render(true) +
+ + +
`, + buttons: [{ + action: "update", + label: "Update", + icon: ``, + }, + { + action: "copy", + label: "Create Copy", + icon: ``, + }, + { + action: "delete", + label: "Delete", + icon: ``, + }, + { + action: "new", + label: "Add New", + icon: ``, + }], + submit: async result => { + if (result === "update") { + let preset = document.getElementById("presets").value + new PresetConfig(preset).render(true); + } + else if (result === "copy") { + let preset = document.getElementById("presets").value + preset = deepClone(preset); + delete preset.id; + new PresetConfig(preset).render(true); + } + else if (result === "delete") { + let preset = document.getElementById("presets").value + let index = presets.findIndex(p => p.id === preset); + const proceed = await foundry.applications.api.DialogV2.confirm({ + window: { + title: "Conformation" + }, + content: `Are you sure you want to remove this preset`, + }) + if (proceed) { + presets.splice(index, 1); + game.settings.set("ATL", "presets", presets); } - }, - four: { - label: "Add New", - icon: ``, - callback: () => new PresetConfig().render(true) + //else presetSelector.render(true); + } + else if (result === "new") { + new PresetConfig().render(true); } } }); @@ -352,7 +347,7 @@ class ATL { const detectionModes = getProperty(overrides, "detectionModes") || duplicate(getProperty(originals, "detectionModes")) || - []; + []; // find the existing one or create a new one let dm = detectionModes.find(dm => dm.id === id); if (!dm) { @@ -538,15 +533,15 @@ window.ATLUpdate = ATLUpdate Hooks.on('init', () => { ATL.init(); if (game.release.generation >= 13) { - Hooks.on('getSceneControlButtons', controls => { - if ( !game.user.isGM ) return; - controls.lighting.tools.atlLights= { - name: "atlLights", - title: "ATL Presets", - icon: "fas fa-plus-circle", - onChange: (event, active) => ATL.UpdatePresets(), - button: true - }; + Hooks.on('getSceneControlButtons', controls => { + if (!game.user.isGM) return; + controls.lighting.tools.atlLights = { + name: "atlLights", + title: "ATL Presets", + icon: "fas fa-plus-circle", + onChange: (event, active) => ATL.UpdatePresets(), + button: true + }; }); } else { From 1205b4e36127b0b976a9ab28ea421cf41eb20f26 Mon Sep 17 00:00:00 2001 From: Peterlankton <61578137+Kapuzenjoe@users.noreply.github.com> Date: Mon, 23 Jun 2025 18:46:50 +0200 Subject: [PATCH 2/7] initial upgrade preset-config to V2 and Change preset.name to preset.label --- .DS_Store | Bin 0 -> 6148 bytes src/activeLighting.js | 34 ++- src/preset-config.js | 289 +++++++++++++++----- src/updateManager.js | 16 +- templates/appearance.hbs | 70 +++++ templates/{preset-config.hbs => header.hbs} | 46 +--- templates/identity.hbs | 37 +++ templates/light.hbs | 41 +++ templates/resources.hbs | 36 +++ templates/vision.hbs | 83 ++++++ 10 files changed, 525 insertions(+), 127 deletions(-) create mode 100644 .DS_Store create mode 100644 templates/appearance.hbs rename templates/{preset-config.hbs => header.hbs} (79%) create mode 100644 templates/identity.hbs create mode 100644 templates/light.hbs create mode 100644 templates/resources.hbs create mode 100644 templates/vision.hbs diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..17106eadb3b5dcd836848f0a0542ed572f5457c5 GIT binary patch literal 6148 zcmeH~J&pn~427S8m5^vCDbsKOZV;j21bYFrOM^5L1<>c{`|P-3c55_RJxk7uop^q} zVloC`$LHk$Yyqt4uGsr9F=PCJCmy(B#Qk#r9=~q4(bHJuUJvNJ#_M`6OGH2fL_h>Y zKm=w)AP#Y!|C<>-lO9C`L|`5S{QFSot~IrFjZX)MXaT4zro%XoUV>UYL9MB+D>F39 z?!mIuq7CtUlv7LYtEsJPFNbCGVR>isE{0~k999_6tcGY10TGxGSoV19=l_ZRSN}gL zQ78f;@XrX?YWN(Ee5pKJf4!dP&zbdkqf=u$hnJrK27VOp=wVzhKB3ms)|DBWegp!8 J1`&8Gfgkjb6RH3J literal 0 HcmV?d00001 diff --git a/src/activeLighting.js b/src/activeLighting.js index 1cfc08b..6f627aa 100644 --- a/src/activeLighting.js +++ b/src/activeLighting.js @@ -8,7 +8,7 @@ class ATL { static init() { let defaultPresets = [ { - name: "torch", + label: "torch", light: { dim: 40, bright: 20, @@ -23,7 +23,7 @@ class ATL { id: "ATLPresetTorch" }, { - name: "lantern", + label: "lantern", light: { dim: 60, bright: 30, @@ -39,7 +39,7 @@ class ATL { }, { - name: "candle", + label: "candle", light: { dim: 10, bright: 2, @@ -55,7 +55,7 @@ class ATL { }, { - name: "flashlight", + label: "flashlight", light: { dim: 60, bright: 30, @@ -91,6 +91,15 @@ class ATL { } static async ready() { + //Update Workaround for change name to label + let presets = await game.settings.get("ATL", "presets") + for (let preset of presets) { + if (!preset.label) { + preset.label = preset.name + delete preset.name + } + } + const newTransferral = game.release.generation >= 11 && !CONFIG.ActiveEffect.legacyTransferral; const getEffects = (actor) => { if (!actor) return []; @@ -210,7 +219,7 @@ class ATL { content: `
- +
`, buttons: [{ action: "update", @@ -234,14 +243,17 @@ class ATL { }], submit: async result => { if (result === "update") { - let preset = document.getElementById("presets").value - new PresetConfig(preset).render(true); + let updatePreset = document.getElementById("presets").value + let preset = presets.find(p => p.id === updatePreset) + + new PresetConfig({},preset).render(true); } else if (result === "copy") { - let preset = document.getElementById("presets").value + let updatePreset = document.getElementById("presets").value + let preset = presets.find(p => p.id === updatePreset) preset = deepClone(preset); delete preset.id; - new PresetConfig(preset).render(true); + new PresetConfig({},preset).render(true); } else if (result === "delete") { let preset = document.getElementById("presets").value @@ -314,7 +326,7 @@ class ATL { if (updateKey === "preset") { // get the matching preset let presetArray = game.settings.get("ATL", "presets") - let preset = presetArray.find(i => i.name === change.value) + let preset = presetArray.find(i => i.label === change.value) if (!preset) { console.error(`ATL: No preset ${change.value} found`) continue; @@ -332,7 +344,7 @@ class ATL { if ("light.angle" in preset) preset["light.angle"] = parseInt(preset["light.angle"]); // remove preset-specific properties delete preset.id - delete preset.name + delete preset.label console.log("ATE | apply preset", change.value, preset); Object.entries(preset) .forEach(([key, value]) => { diff --git a/src/preset-config.js b/src/preset-config.js index c2a9f65..4542e14 100644 --- a/src/preset-config.js +++ b/src/preset-config.js @@ -1,20 +1,21 @@ +const { HandlebarsApplicationMixin, Application, DocumentSheetV2 } = foundry.applications.api; /** * The Application used for defining a preset configuration that can be used by the `ATL.preset` * active effect key. It can handle updating an existing preset as well as creating a new one. */ -export class PresetConfig extends FormApplication { +export class PresetConfig extends HandlebarsApplicationMixin(Application) { /** - * Create a new application to add/edit a preset. + * Create a new application to add/edit a preset. + * @param {ApplicationConfiguration} options Options used to configure the Application instance * @param {Object} object The ATL preset, or `undefined` if creating a new one from scratch - * @param {FormApplicationOptions} options Application configuration options */ - constructor(object = {}, options = {}) { - super(object, options); + constructor(options, object = {}) { + super(options); /** * The token change preset */ - this.preset = this.object; + this.preset = object; /** * Whether this app is creating a new preset or not @@ -27,29 +28,171 @@ export class PresetConfig extends FormApplication { this.fieldsChanged = []; } - static get defaultOptions() { - return foundry.utils.mergeObject(super.defaultOptions, { - classes: ["sheet", "preset-config"], + /** @inheritDoc */ + static DEFAULT_OPTIONS = { + classes: ["preset-config"], + tag: "form", + position: { + width: 560 + }, + window: { title: "ATL Light Editor", - template: "modules/ATL/templates/preset-config.hbs", - width: 480, - height: "auto", + icon: "fas fa-plus-circle", + contentClasses: ["standard-form"], + }, + form: { + handler: PresetConfig.#onSubmit, + //submitOnChange: false, + closeOnSubmit: true + } + } + + /** @override */ + static PARTS = { + header: { + template: "modules/ATL/templates/header.hbs", + }, + tabs: { + template: "templates/generic/tab-navigation.hbs" + }, + appearance: { + template: "modules/ATL/templates/appearance.hbs", scrollable: [""] + }, + identity: { + template: "modules/ATL/templates/identity.hbs", scrollable: [""] + }, + vision: { + template: "modules/ATL/templates/vision.hbs", scrollable: [""] + }, + light: { + template: "modules/ATL/templates/light.hbs", scrollable: [""] + }, + resources: { + template: "modules/ATL/templates/resources.hbs", scrollable: [""] + }, + footer: { + template: "templates/generic/form-footer.hbs", + }, + }; + + /** @override */ + static TABS = { + sheet: { tabs: [ - { - navSelector: '.tabs[data-group="main"]', - contentSelector: "form", - initial: "appearance", - }, - { - navSelector: '.tabs[data-group="light"]', - contentSelector: '.tab[data-tab="light"]', - initial: "basic", - }, + { id: "identity", icon: "fa-solid fa-memo-pad" }, + { id: "appearance", icon: "fa-solid fa-square-user" }, + { id: "vision", icon: "fa-solid fa-eye" }, + { id: "light", icon: "fa-solid fa-lightbulb" }, + { id: "resources", icon: "fa-solid fa-heart" } ], - closeOnSubmit: true, - }); + initial: "appearance", + labelPrefix: "TOKEN.TABS" + } + }; + + /** + * Localized Token Display Modes + * @returns {Record} + */ + static get DISPLAY_MODES() { + TokenApplication.#DISPLAY_MODES ??= Object.entries(CONST.TOKEN_DISPLAY_MODES).reduce((modes, [key, value]) => { + modes[value] = game.i18n.localize(`TOKEN.DISPLAY_${key}`); + return modes; + }, {}); + return TokenApplication.#DISPLAY_MODES; + } + + static #DISPLAY_MODES; + + /** + * Localized Token Dispositions + * @returns {Record} + */ + static get TOKEN_DISPOSITIONS() { + PresetConfig.#TOKEN_DISPOSITIONS ??= Object.entries(CONST.TOKEN_DISPOSITIONS) + .reduce((dispositions, [key, value]) => { + dispositions[value] = game.i18n.localize(`TOKEN.DISPOSITION.${key}`); + return dispositions; + }, {}); + return PresetConfig.#TOKEN_DISPOSITIONS; + } + + static #TOKEN_DISPOSITIONS; + + /** + * Localized Token Turn Marker modes + * @returns {Record} + */ + static get TURN_MARKER_MODES() { + PresetConfig.#TURN_MARKER_MODES ??= Object.entries(CONST.TOKEN_TURN_MARKER_MODES) + .reduce((modes, [key, value]) => { + modes[value] = game.i18n.localize(`TOKEN.TURNMARKER.MODES.${key}`); + return modes; + }, {}); + return PresetConfig.#TURN_MARKER_MODES; + } + + static #TURN_MARKER_MODES; + + /** + * Localized Token Shapes + * @returns {Record} + */ + static get TOKEN_SHAPES() { + PresetConfig.#TOKEN_SHAPES ??= Object.entries(CONST.TOKEN_SHAPES) + .reduce((shapes, [key, value]) => { + shapes[value] = game.i18n.localize(`TOKEN.SHAPES.${key}.label`); + return shapes; + }, {}); + return PresetConfig.#TOKEN_SHAPES; } + static #TOKEN_SHAPES; + + /* -------------------------------------------- */ + + /** + * Process form submission for the sheet + * @this {PresetConfig} The handler is called with the application as its bound scope + * @param {SubmitEvent} event The originating form submission event + * @param {HTMLFormElement} form The form element that was submitted + * @param {FormDataExtended} formData Processed data for the submitted form + * @returns {Promise} + */ + static async #onSubmit(event, form, formData) { + console.log("ATL |", "_updateObject called with formData:", formData.object); + // Mirror token scale + if ("scale" in formData.object) { + formData.object["texture.scaleX"] = formData.object.scale * (formData.object.mirrorX ? -1 : 1); + formData.object["texture.scaleY"] = formData.object.scale * (formData.object.mirrorY ? -1 : 1); + } + + if (this.fieldsChanged.includes("scale" || "mirrorX" || "mirrorY")) this.fieldsChanged.push("texture.scaleX", "texture.scaleY"); + for (const key of ["scale", "mirrorX", "mirrorY"]) delete formData.object[key]; + + // Set default name if creating a new preset with no name + if (this.newMode && !formData.object.label) { + const presets = game.settings.get("ATL", "presets"); + const count = presets?.length; + formData.object.label = `New Preset (${count + 1})`; + } + + // Remove name change if updating a preset and trying to clear the name + //if (!this.newMode && "label" in formData.object && !formData.object.label) delete formData.object.label; + + // apply the changes to the original preset + Object.entries(formData.object) + .filter(([k, _]) => this.fieldsChanged.includes(k)) + .forEach(([k, v]) => { + if (v === "" || v === null) this._clearProperty(this.preset, k); + else foundry.utils.setProperty(this.preset, k, v); + }); + console.log("updated preset:", this.preset); + + PresetConfig.savePreset(this.preset); + } + + static savePreset(preset) { // put all the presets into a collection const collection = new Collection(); @@ -59,22 +202,24 @@ export class PresetConfig extends FormApplication { // add or update in collection if (!preset.id) preset.id = foundry.utils.randomID(); collection.set(preset.id, preset); - // save collection presets = collection.toJSON(); game.settings.set("ATL", "presets", presets); } - getData(options) { - const gridUnits = game.system.gridUnits; + /* -------------------------------------------- */ + + /** @inheritDoc */ + async _prepareContext(options) { + const context = await super._prepareContext(options); // prepare Preset data - const preset = foundry.utils.deepClone(this.object); + const preset = foundry.utils.deepClone(this.preset); - return { + return Object.assign(context, { + rootId: this.id, object: preset, - gridUnits: gridUnits || game.i18n.localize("GridUnits"), - colorationTechniques: AdaptiveLightingShader.SHADER_TECHNIQUES, + gridUnits: game.i18n.localize("GridUnits"), visionModes: Object.values(CONFIG.Canvas.visionModes).filter((f) => f.tokenConfig), lightAnimations: Object.entries(CONFIG.Canvas.lightAnimations).reduce( (obj, e) => { @@ -83,57 +228,60 @@ export class PresetConfig extends FormApplication { }, { "": game.i18n.localize("None") } ), - scale: Math.abs(this.object.texture?.scaleX || 1), - }; + shapes: PresetConfig.TOKEN_SHAPES, + colorationTechniques: foundry.canvas.rendering.shaders.AdaptiveLightingShader.SHADER_TECHNIQUES, + scale: (Math.abs(this.preset.texture?.scaleX) || 1), + mirrorX: this.preset.texture?.scaleX < 0, + mirrorY: this.preset.texture?.scaleY < 0, + textureFitModes: CONST.TEXTURE_DATA_FIT_MODES.reduce((obj, fit) => { + obj[fit] = game.i18n.localize(`TEXTURE_DATA.FIT.${fit}`); + return obj; + }, {}), + movementActions: Object.entries(CONFIG.Token.movement.actions).reduce( + (choices, [action, { label, canSelect }]) => { + if (canSelect(this.token)) choices[action] = label; + return choices; + }, {}), + dispositions: PresetConfig.TOKEN_DISPOSITIONS, + buttons: [ + { type: "submit", icon: "fa-solid fa-save", label: "SETTINGS.Save" }, + ] + }); } + /* -------------------------------------------- */ - _getSubmitData(updateData = {}) { - const formData = super._getSubmitData(updateData); + /** @inheritDoc */ + async _preFirstRender(context, options) { + await super._preFirstRender(context, options); + } - // Mirror token scale - if ("scale" in formData) { - formData["texture.scaleX"] = formData.scale * (formData.mirrorX ? -1 : 1); - formData["texture.scaleY"] = formData.scale * (formData.mirrorY ? -1 : 1); - } - ["scale", "mirrorX", "mirrorY"].forEach((k) => delete formData[k]); - if (this.fieldsChanged.includes("scale")) this.fieldsChanged.push("texture.scaleX", "texture.scaleY"); + /* -------------------------------------------- */ - // Set default name if creating a new preset with no name - if (this.newMode && !formData.name) { - const presets = game.settings.get("ATL", "presets"); - const count = presets?.length; - formData.name = `New Preset (${count + 1})`; + /** @inheritDoc */ + async _preparePartContext(partId, context, options) { + context = await super._preparePartContext(partId, context, options); + + const tab = context.tabs[partId]; + if (tab) { + context.tab = tab; } + return context; + } - // Remove name change if updating a preset and trying to clear the name - if (!this.newMode && "name" in formData && !formData.name) delete formData.name; + /* -------------------------------------------- */ - return formData; - } - async _onChangeInput(event) { - super._onChangeInput(event); + /** @inheritDoc */ + _onChangeForm(formConfig, event) { + super._onChangeForm(formConfig, event); // save the field's name that was changed const el = event.target; + console.log("onChange", el) if (el.name) this.fieldsChanged.push(el.name); // colorPicker has matching name in the dataset else if (el.dataset.edit) this.fieldsChanged.push(el.dataset.edit); - } - - async _updateObject(event, formData) { - console.log("ATL |", "_updateObject called with formData:", formData); - - // apply the changes to the original preset - Object.entries(formData) - .filter(([k, _]) => this.fieldsChanged.includes(k)) - .forEach(([k, v]) => { - if (v === "" || v === null) this._clearProperty(this.preset, k); - else foundry.utils.setProperty(this.preset, k, v); - }); - console.log("updated preset:", this.preset); - - PresetConfig.savePreset(this.preset); + console.log(this.fieldsChanged) } _clearProperty(object, key) { @@ -155,7 +303,7 @@ export class PresetConfig extends FormApplication { // recursivly call to remove empty objects if (parts) { const remainingKey = parts.join("."); - if (object[remainingKey] && isEmpty(object[remainingKey])) + if (object[remainingKey] && foundry.utils.isEmpty(object[remainingKey])) this._clearProperty(object, remainingKey); } } @@ -163,4 +311,5 @@ export class PresetConfig extends FormApplication { // Return changed status return cleared; } -} + +} diff --git a/src/updateManager.js b/src/updateManager.js index 47f6bc1..51477af 100644 --- a/src/updateManager.js +++ b/src/updateManager.js @@ -64,7 +64,7 @@ export class ATLUpdate { if (change.key.includes("ATL")) { changeFound = true; updates.push(this.v9UpdateEffect(duplicate(change))) - } + } else updates.push(change); } if (changeFound) { @@ -209,16 +209,16 @@ export class ATLUpdate { return newData } - static async flagBuster(actor){ + static async flagBuster(actor) { console.warn(`Updating ${actor.name}`) let flag = actor.getFlag("ATL", "originals") - if(!flag) return ui.notifications.notify(`No Flag for ${actor.name}`) - let updates = mergeObject(actor.data.token, flag, {inplace: false}) - await actor.update({token : updates}) + if (!flag) return ui.notifications.notify(`No Flag for ${actor.name}`) + let updates = mergeObject(actor.data.token, flag, { inplace: false }) + await actor.update({ token: updates }) } - static async massFlagUpdate(){ - for(let actor of game.actors){ + static async massFlagUpdate() { + for (let actor of game.actors) { await this.flagBuster(actor) } } @@ -351,7 +351,7 @@ export class ATLUpdate { if (brightness !== 0) changes.push({ key: "ATL.sight.brightness", value: brightness, mode, priority }); } - + if (changeFound) return changes; } } diff --git a/templates/appearance.hbs b/templates/appearance.hbs new file mode 100644 index 0000000..84582e0 --- /dev/null +++ b/templates/appearance.hbs @@ -0,0 +1,70 @@ +
+
+ +
+ +
+
+ +
+ +
+ + + + +
+
+ +
+ +
+ + + + +
+

{{localize "TOKEN.AnchorHint"}}

+
+ +
+ +
+ +
+
+ +
+ +
+ + +
+
+ + {{!-- {{formGroup fields.texture.fields.tint value=source.texture.tint placeholder="#ffffff" rootId=rootId}} + {{formGroup fields.alpha value=source.alpha step=0.05 rootId=rootId}} + {{formGroup fields.lockRotation value=source.lockRotation rootId=rootId}} + +
+ {{localize "TOKEN.RING.SHEET.legend"}} + {{formGroup fields.ring.fields.enabled value=source.ring.enabled rootId=rootId}} + {{formGroup fields.ring.fields.colors.fields.ring value=source.ring.colors.ring rootId=rootId}} + {{formGroup fields.ring.fields.colors.fields.background value=source.ring.colors.background rootId=rootId}} + {{formGroup fields.ring.fields.subject.fields.texture value=source.ring.subject.texture rootId=rootId}} + {{formGroup fields.ring.fields.subject.fields.scale value=source.ring.subject.scale max=3 step=0.02 + rootId=rootId}} + {{formGroup fields.ring.fields.effects value=source.ring.effects input=ringEffectsInput stacked=true + rootId=rootId}} +
--}} +
\ No newline at end of file diff --git a/templates/preset-config.hbs b/templates/header.hbs similarity index 79% rename from templates/preset-config.hbs rename to templates/header.hbs index a975f11..92c3298 100644 --- a/templates/preset-config.hbs +++ b/templates/header.hbs @@ -1,38 +1,13 @@ -
-
- - -
- - - - - -
-
- -
- - - - -
-
- -
- {{ rangePicker name="scale" value=scale min="0.2" max="3.0" step="0.1" }} -
+ +
+ +
-
- +{{!--
@@ -56,7 +31,7 @@
@@ -146,7 +121,7 @@

{{ localize 'LIGHT.ColorationTechniqueHint' }}

@@ -192,10 +167,5 @@

{{ localize 'LIGHT.ShadowsHint' }}

- - -
- -
+ --}} -
diff --git a/templates/identity.hbs b/templates/identity.hbs new file mode 100644 index 0000000..ef73d31 --- /dev/null +++ b/templates/identity.hbs @@ -0,0 +1,37 @@ +
+
+ +
+ +
+
+ +
+ +
+ + {{formInput fields.x value=source.x id=(concat rootId "-x") disabled=(not isGM) + placeholder=(localize "Pixels")}} + + {{formInput fields.y value=source.y id=(concat rootId "-y") disabled=(not isGM) + placeholder=(localize "Pixels")}} +
+
+ {{formGroup fields.elevation value=source.elevation classes="slim" units=gridUnits rootId=rootId}} + {{formGroup fields.sort value=source.sort classes="slim" rootId=rootId}} + + + {{formGroup fields.rotation value=source.rotation classes="slim" units=(localize "Degrees") rootId=rootId}} + {{formGroup fields.movementAction value=source.movementAction choices=movementActions classes="slim" blank="Default" + localize=true rootId=rootId}} + {{formGroup fields.occludable.fields.radius value=source.occludable.radius units=gridUnits classes="slim" + rootId=rootId}} +
+ +
+ +
+
+
\ No newline at end of file diff --git a/templates/light.hbs b/templates/light.hbs new file mode 100644 index 0000000..25b2b5b --- /dev/null +++ b/templates/light.hbs @@ -0,0 +1,41 @@ +
+
+ {{localize "TOKEN.SECTIONS.basic"}} +
+ +
+ + {{formInput lightFields.dim id=(concat rootId "-light.dim") value=source.light.dim}} + + {{formInput lightFields.bright id=(concat rootId "-light.bright") value=source.light.bright}} +
+

{{localize "AMBIENT_LIGHT.LABELS.radiusHint"}}

+
+ + {{formGroup lightFields.angle value=source.light.angle classes="slim" units=(localize "Degrees") rootId=rootId}} + {{formGroup lightFields.color value=source.light.color rootId=rootId}} + {{formGroup lightFields.alpha value=source.light.alpha step=0.05 rootId=rootId}} + {{formGroup lightFields.priority value=source.light.priority rootId=rootId}} + {{formGroup lightFields.negative value=source.light.negative rootId=rootId}} +
+ +
+ {{localize "TOKEN.SECTIONS.animation"}} + {{formGroup lightFields.animation.fields.type value=source.light.animation.type + choices=lightAnimations labelAttr="label" blank="None" sort=true rootId=rootId localize=true}} + {{formGroup lightFields.animation.fields.speed value=source.light.animation.speed rootId=rootId}} + {{formGroup lightFields.animation.fields.reverse value=source.light.animation.reverse rootId=rootId}} + {{formGroup lightFields.animation.fields.intensity value=source.light.animation.intensity rootId=rootId}} +
+ +
+ {{localize "TOKEN.SECTIONS.advanced"}} + {{formGroup lightFields.coloration value=source.light.coloration + choices=colorationTechniques valueAttr="id" labelAttr="label" rootId=rootId localize=true}} + {{formGroup lightFields.luminosity value=source.light.luminosity step=0.05 rootId=rootId}} + {{formGroup lightFields.attenuation value=source.light.attenuation step=0.05 rootId=rootId}} + {{formGroup lightFields.saturation value=source.light.saturation step=0.05 rootId=rootId}} + {{formGroup lightFields.contrast value=source.light.contrast step=0.05 rootId=rootId}} + {{formGroup lightFields.shadows value=source.light.shadows step=0.05 rootId=rootId}} +
+
diff --git a/templates/resources.hbs b/templates/resources.hbs new file mode 100644 index 0000000..03c23a0 --- /dev/null +++ b/templates/resources.hbs @@ -0,0 +1,36 @@ +
+ {{formGroup fields.displayBars value=source.displayBars choices=displayModes rootId=rootId localize=true}} + {{formGroup fields.bar1.fields.attribute value=source.bar1.attribute choices=barAttributes blank=(localize "None") + labelAttr="label" valueAttr="value" rootId=rootId}} + {{#unless isDefault}} +
+ +
+ + / + +
+
+ {{/unless}} + {{formGroup fields.bar2.fields.attribute choices=barAttributes value=source.bar2.attribute blank=(localize "None") + labelAttr="label" valueAttr="value" rootId=rootId}} + {{#unless isDefault}} +
+ +
+ + / + +
+
+ {{/unless}} + +
+ {{localize "TOKEN.TURNMARKER.SHEET.legend"}} + {{formGroup fields.turnMarker.fields.mode value=source.turnMarker.mode choices=turnMarkerModes}} + {{formGroup fields.turnMarker.fields.animation value=source.turnMarker.animation options=turnMarkerAnimations + blank=""}} + {{formGroup fields.turnMarker.fields.src value=source.turnMarker.src}} + {{formGroup fields.turnMarker.fields.disposition value=source.turnMarker.disposition}} +
+
diff --git a/templates/vision.hbs b/templates/vision.hbs new file mode 100644 index 0000000..5f3f115 --- /dev/null +++ b/templates/vision.hbs @@ -0,0 +1,83 @@ +
+
+ {{localize "TOKEN.SightHeaderBasic"}} + {{formGroup sightFields.enabled value=source.sight.enabled rootId=rootId}} + +
+ +
+ +
+

{{localize "TOKEN.FIELDS.sight.range.hint"}}

+
+ + {{formGroup sightFields.angle value=source.sight.angle classes="slim" units=(localize "Degrees") rootId=rootId}} + {{formGroup sightFields.visionMode value=source.sight.visionMode choices=visionModes rootId=rootId sort=true localize=true}} +
+ +
+ {{localize "TOKEN.SightHeaderDetection"}} +
+
{{localize "TOKEN.DetectionMode"}}
+
{{localize "TOKEN.DetectionRange"}} ({{gridUnits}})
+
{{localize "TOKEN.DetectionEnabled"}}
+
+ +
+
+ + {{#each preparedDetectionModes as |mode|}} +
+
+ +
+
+ +
+
+ +
+
+
+ {{/each}} + + {{#each sourceDetectionModes as |mode i|}} +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ {{/each}} +
+ +
+ {{localize "TOKEN.SightHeaderAdvanced"}} + {{formGroup sightFields.color value=source.sight.color rootId=rootId}} + {{formGroup sightFields.attenuation value=source.sight.attenuation step=0.05 rootId=rootId}} + {{formGroup sightFields.brightness value=source.sight.brightness step=0.05 rootId=rootId}} + {{formGroup sightFields.saturation value=source.sight.saturation step=0.05 rootId=rootId}} + {{formGroup sightFields.contrast value=source.sight.contrast step=0.05 rootId=rootId}} +
+
From 5111d78e6138b2a23cc57665a11300ac99765ba8 Mon Sep 17 00:00:00 2001 From: Peterlankton <61578137+Kapuzenjoe@users.noreply.github.com> Date: Tue, 24 Jun 2025 14:48:40 +0200 Subject: [PATCH 3/7] more templates updated --- src/preset-config.js | 2 +- templates/header.hbs | 175 ++-------------------------------------- templates/identity.hbs | 54 +++++++++---- templates/light.hbs | 153 ++++++++++++++++++++++++++++++----- templates/resources.hbs | 26 ------ templates/vision.hbs | 50 +++++++----- 6 files changed, 209 insertions(+), 251 deletions(-) diff --git a/src/preset-config.js b/src/preset-config.js index 4542e14..6225541 100644 --- a/src/preset-config.js +++ b/src/preset-config.js @@ -178,7 +178,7 @@ export class PresetConfig extends HandlebarsApplicationMixin(Application) { } // Remove name change if updating a preset and trying to clear the name - //if (!this.newMode && "label" in formData.object && !formData.object.label) delete formData.object.label; + if (!this.newMode && "label" in formData.object && !formData.object.label) delete formData.object.label; // apply the changes to the original preset Object.entries(formData.object) diff --git a/templates/header.hbs b/templates/header.hbs index 92c3298..184ad20 100644 --- a/templates/header.hbs +++ b/templates/header.hbs @@ -1,171 +1,6 @@ - - -
- -
- -
-
- -{{!-- -
- - -
- -
- {{numberInput object.sight.range name="sight.range" placeholder=gridUnits min="0" step="any"}} -
-

{{ localize 'TOKEN.VisionRangeHint' }}

-
- -
- -
- {{numberInput object.sight.angle name="sight.angle" placeholder=(localize "Degrees")}} -
-

{{ localize 'TOKEN.VisionAngleHint' }}

-
- -
- -
- -
-

{{ localize 'TOKEN.VisionModeHint' }}

-
+
+ +
+
- - -
- - -
-
- -
- - - - -
-

{{ localize 'LIGHT.RadiusHint' }}

-
- -
- -
- - -
-
- -
- -
- {{colorPicker name="light.color" value=object.light.color}} -
-
- -
- -
- {{rangePicker name="light.alpha" value=object.light.alpha min="0" max="1" step="0.05"}} -
-

{{ localize 'LIGHT.ColorHint' }}

-
-
- -
-
- -
- -
-
- -
- -
- {{rangePicker name="light.animation.speed" value=object.light.animation.speed min="0" max="10" step="1"}} -
-
- -
- -
- -
-
- -
- -
- {{rangePicker name="light.animation.intensity" value=object.light.animation.intensity min="1" max="10" step="1"}} -
-

{{ localize "LIGHT.AnimationHint" }}

-
-
- -
-
- -
- -
-

{{ localize 'LIGHT.ColorationTechniqueHint' }}

-
- -
- -
- {{ rangePicker name="light.luminosity" value=object.light.luminosity min="-1" max="1" step="0.05" }} -
-

{{ localize 'LIGHT.LuminosityHint' }}

-
- -
- -
- {{ rangePicker name="light.attenuation" value=object.light.attenuation min="0" max="1" step="0.05" }} -
-

{{ localize 'LIGHT.AttenuationHint' }}

-
- -
- -
- {{ rangePicker name="light.saturation" value=object.light.saturation min="-1" max="1" step="0.05" }} -
-

{{ localize 'LIGHT.SaturationHint' }}

-
- -
- -
- {{ rangePicker name="light.contrast" value=object.light.contrast min="-1" max="1" step="0.05" }} -
-

{{ localize 'LIGHT.ContrastHint' }}

-
- -
- -
- {{ rangePicker name="light.shadows" value=object.light.shadows min="0" max="1" step="0.05" }} -
-

{{ localize 'LIGHT.ShadowsHint' }}

-
-
-
--}} - +
\ No newline at end of file diff --git a/templates/identity.hbs b/templates/identity.hbs index ef73d31..8ac9870 100644 --- a/templates/identity.hbs +++ b/templates/identity.hbs @@ -5,32 +5,58 @@
-
- {{formInput fields.x value=source.x id=(concat rootId "-x") disabled=(not isGM) + {{numberInput fields.x name="x" value="{{object.x}}" id=(concat rootId "-x") placeholder=(localize "Pixels")}} - {{formInput fields.y value=source.y id=(concat rootId "-y") disabled=(not isGM) + {{numberInput fields.y name="y" value="{{object.y}}" id=(concat rootId "-y") placeholder=(localize "Pixels")}}
- {{formGroup fields.elevation value=source.elevation classes="slim" units=gridUnits rootId=rootId}} - {{formGroup fields.sort value=source.sort classes="slim" rootId=rootId}} - - - {{formGroup fields.rotation value=source.rotation classes="slim" units=(localize "Degrees") rootId=rootId}} - {{formGroup fields.movementAction value=source.movementAction choices=movementActions classes="slim" blank="Default" - localize=true rootId=rootId}} - {{formGroup fields.occludable.fields.radius value=source.occludable.radius units=gridUnits classes="slim" - rootId=rootId}}
- + +
+ {{numberInput fields.elevation name="elevation" value="{{object.elevation}}" placeholder="0" units=gridUnits + step="any"}} +
+
+
+ +
+ {{numberInput fields.sort name="sort" value="{{object.sort}}" placeholder="0"}} +
+
+
+ +
+ {{numberInput fields.rotation name="rotation" value="{{object.rotation}}" placeholder="0"}} +
+
+
+ +
+ +
+
+
+ +
+ {{numberInput fields.occludable.fields.radius name="occludable.radius" value="{{object.occludable.radius}}" + placeholder="0" units=gridUnits + step="any"}} +
+

{{localize "TOKEN.FIELDS.occludable.radius.hint"}}

+
+
+
diff --git a/templates/light.hbs b/templates/light.hbs index 25b2b5b..0065025 100644 --- a/templates/light.hbs +++ b/templates/light.hbs @@ -5,37 +5,146 @@
- {{formInput lightFields.dim id=(concat rootId "-light.dim") value=source.light.dim}} + - {{formInput lightFields.bright id=(concat rootId "-light.bright") value=source.light.bright}} +

{{localize "AMBIENT_LIGHT.LABELS.radiusHint"}}

- - {{formGroup lightFields.angle value=source.light.angle classes="slim" units=(localize "Degrees") rootId=rootId}} - {{formGroup lightFields.color value=source.light.color rootId=rootId}} - {{formGroup lightFields.alpha value=source.light.alpha step=0.05 rootId=rootId}} - {{formGroup lightFields.priority value=source.light.priority rootId=rootId}} - {{formGroup lightFields.negative value=source.light.negative rootId=rootId}} +
+ +
+ +
+

{{localize "LIGHT.FIELDS.angle.hint"}}

+
+
+ +
+ +
+

{{localize "LIGHT.FIELDS.color.hint"}}

+
+
+ +
+ +
+

{{ localize 'LIGHT.FIELDS.alpha.hint' }}

+
+
+ +
+ +
+

{{localize "LIGHT.FIELDS.priority.hint"}}

+
+
+ +
+ +
+

{{localize "LIGHT.FIELDS.negative.hint"}}

+
{{localize "TOKEN.SECTIONS.animation"}} - {{formGroup lightFields.animation.fields.type value=source.light.animation.type - choices=lightAnimations labelAttr="label" blank="None" sort=true rootId=rootId localize=true}} - {{formGroup lightFields.animation.fields.speed value=source.light.animation.speed rootId=rootId}} - {{formGroup lightFields.animation.fields.reverse value=source.light.animation.reverse rootId=rootId}} - {{formGroup lightFields.animation.fields.intensity value=source.light.animation.intensity rootId=rootId}} +
+ +
+ +
+
+ {{!-- {{formGroup lightFields.animation.fields.type value=source.light.animation.type + choices=lightAnimations labelAttr="label" blank="None" sort=true rootId=rootId localize=true}} --}} +
+ +
+ +
+

{{localize "LIGHT.FIELDS.animation.speed.hint"}}

+
+
+ +
+ +
+
+
+ +
+ +
+

{{localize "LIGHT.FIELDS.animation.intensity.hint"}}

+
-
+
{{localize "TOKEN.SECTIONS.advanced"}} - {{formGroup lightFields.coloration value=source.light.coloration - choices=colorationTechniques valueAttr="id" labelAttr="label" rootId=rootId localize=true}} - {{formGroup lightFields.luminosity value=source.light.luminosity step=0.05 rootId=rootId}} - {{formGroup lightFields.attenuation value=source.light.attenuation step=0.05 rootId=rootId}} - {{formGroup lightFields.saturation value=source.light.saturation step=0.05 rootId=rootId}} - {{formGroup lightFields.contrast value=source.light.contrast step=0.05 rootId=rootId}} - {{formGroup lightFields.shadows value=source.light.shadows step=0.05 rootId=rootId}} +
+ +
+ +
+

{{ localize 'LIGHT.FIELDS.coloration.hint' }}

+
+ +
+ +
+ +
+

{{ localize 'LIGHT.FIELDS.luminosity.hint' }}

+
+ +
+ +
+ +
+

{{ localize 'LIGHT.FIELDS.attenuation.hint' }}

+
+ +
+ +
+ +
+

{{ localize 'LIGHT.FIELDS.saturation.hint' }}

+
+ +
+ +
+ +
+

{{ localize 'LIGHT.FIELDS.contrast.hint' }}

+
+ +
+ +
+ +
+

{{ localize 'LIGHT.FIELDS.shadows.hint' }}

+
- + \ No newline at end of file diff --git a/templates/resources.hbs b/templates/resources.hbs index 03c23a0..f2b6616 100644 --- a/templates/resources.hbs +++ b/templates/resources.hbs @@ -1,30 +1,4 @@
- {{formGroup fields.displayBars value=source.displayBars choices=displayModes rootId=rootId localize=true}} - {{formGroup fields.bar1.fields.attribute value=source.bar1.attribute choices=barAttributes blank=(localize "None") - labelAttr="label" valueAttr="value" rootId=rootId}} - {{#unless isDefault}} -
- -
- - / - -
-
- {{/unless}} - {{formGroup fields.bar2.fields.attribute choices=barAttributes value=source.bar2.attribute blank=(localize "None") - labelAttr="label" valueAttr="value" rootId=rootId}} - {{#unless isDefault}} -
- -
- - / - -
-
- {{/unless}} -
{{localize "TOKEN.TURNMARKER.SHEET.legend"}} {{formGroup fields.turnMarker.fields.mode value=source.turnMarker.mode choices=turnMarkerModes}} diff --git a/templates/vision.hbs b/templates/vision.hbs index 5f3f115..2aa6b93 100644 --- a/templates/vision.hbs +++ b/templates/vision.hbs @@ -1,7 +1,6 @@
{{localize "TOKEN.SightHeaderBasic"}} - {{formGroup sightFields.enabled value=source.sight.enabled rootId=rootId}}
- +

{{localize "TOKEN.FIELDS.sight.range.hint"}}

- - {{formGroup sightFields.angle value=source.sight.angle classes="slim" units=(localize "Degrees") rootId=rootId}} - {{formGroup sightFields.visionMode value=source.sight.visionMode choices=visionModes rootId=rootId sort=true localize=true}} +
+ +
+ {{numberInput object.sight.angle name="sight.angle" placeholder=(localize "Degrees")}} +
+

{{ localize 'TOKEN.FIELDS.sight.angle.hint' }}

+
+
+ +
+ +
+

{{ localize 'TOKEN.FIELDS.sight.visionMode.hint' }}

+
-
+ {{!--
{{localize "TOKEN.SightHeaderDetection"}}
{{localize "TOKEN.DetectionMode"}}
@@ -27,7 +40,7 @@
{{localize "TOKEN.DetectionEnabled"}}
+ data-tooltip aria-label="{{localize " TOKEN.DetectionAdd"}}">
@@ -35,13 +48,13 @@
+ step="any" disabled>
@@ -55,29 +68,30 @@
- +
+ data-tooltip aria-label="{{localize " TOKEN.DetectionRemove"}}">
{{/each}}
- -
+ --}} +{{!--
{{localize "TOKEN.SightHeaderAdvanced"}} {{formGroup sightFields.color value=source.sight.color rootId=rootId}} {{formGroup sightFields.attenuation value=source.sight.attenuation step=0.05 rootId=rootId}} {{formGroup sightFields.brightness value=source.sight.brightness step=0.05 rootId=rootId}} {{formGroup sightFields.saturation value=source.sight.saturation step=0.05 rootId=rootId}} {{formGroup sightFields.contrast value=source.sight.contrast step=0.05 rootId=rootId}} -
-
+
--}} +
\ No newline at end of file From d8c9ef32e8ff1954e9085ce642fd2c099ce1c8e3 Mon Sep 17 00:00:00 2001 From: Peterlankton <61578137+Kapuzenjoe@users.noreply.github.com> Date: Tue, 24 Jun 2025 15:06:01 +0200 Subject: [PATCH 4/7] small fixes --- templates/light.hbs | 2 +- templates/resources.hbs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/templates/light.hbs b/templates/light.hbs index 0065025..46055d2 100644 --- a/templates/light.hbs +++ b/templates/light.hbs @@ -5,7 +5,7 @@
- -
+ {{!--
{{localize "TOKEN.TURNMARKER.SHEET.legend"}} {{formGroup fields.turnMarker.fields.mode value=source.turnMarker.mode choices=turnMarkerModes}} {{formGroup fields.turnMarker.fields.animation value=source.turnMarker.animation options=turnMarkerAnimations blank=""}} {{formGroup fields.turnMarker.fields.src value=source.turnMarker.src}} {{formGroup fields.turnMarker.fields.disposition value=source.turnMarker.disposition}} -
+
--}}
From 8dec8bd9952b1562d782131bdaaa6e95536577a4 Mon Sep 17 00:00:00 2001 From: Peterlankton <61578137+Kapuzenjoe@users.noreply.github.com> Date: Thu, 26 Jun 2025 19:54:32 +0200 Subject: [PATCH 5/7] some bugfixes and new fields --- src/preset-config.js | 16 +---- templates/appearance.hbs | 128 +++++++++++++++++++++++++++++++-------- templates/identity.hbs | 4 +- templates/light.hbs | 6 +- 4 files changed, 109 insertions(+), 45 deletions(-) diff --git a/src/preset-config.js b/src/preset-config.js index 6225541..719f938 100644 --- a/src/preset-config.js +++ b/src/preset-config.js @@ -90,20 +90,6 @@ export class PresetConfig extends HandlebarsApplicationMixin(Application) { } }; - /** - * Localized Token Display Modes - * @returns {Record} - */ - static get DISPLAY_MODES() { - TokenApplication.#DISPLAY_MODES ??= Object.entries(CONST.TOKEN_DISPLAY_MODES).reduce((modes, [key, value]) => { - modes[value] = game.i18n.localize(`TOKEN.DISPLAY_${key}`); - return modes; - }, {}); - return TokenApplication.#DISPLAY_MODES; - } - - static #DISPLAY_MODES; - /** * Localized Token Dispositions * @returns {Record} @@ -175,6 +161,7 @@ export class PresetConfig extends HandlebarsApplicationMixin(Application) { const presets = game.settings.get("ATL", "presets"); const count = presets?.length; formData.object.label = `New Preset (${count + 1})`; + this.fieldsChanged.push("label") } // Remove name change if updating a preset and trying to clear the name @@ -277,7 +264,6 @@ export class PresetConfig extends HandlebarsApplicationMixin(Application) { // save the field's name that was changed const el = event.target; - console.log("onChange", el) if (el.name) this.fieldsChanged.push(el.name); // colorPicker has matching name in the dataset else if (el.dataset.edit) this.fieldsChanged.push(el.dataset.edit); diff --git a/templates/appearance.hbs b/templates/appearance.hbs index 84582e0..97358e4 100644 --- a/templates/appearance.hbs +++ b/templates/appearance.hbs @@ -2,28 +2,48 @@
- + + +
- + - +
+ {{!--
+ +
+ +
+

{{localize "TOKEN.FIELDS.shape.hint"}}

+
--}} +
+ +
+ +
+

{{localize "TOKEN.FIELDS.texture.fit.hint"}}

+
+
- + - +
@@ -31,40 +51,98 @@
- +
- +
-
- {{!-- {{formGroup fields.texture.fields.tint value=source.texture.tint placeholder="#ffffff" rootId=rootId}} - {{formGroup fields.alpha value=source.alpha step=0.05 rootId=rootId}} - {{formGroup fields.lockRotation value=source.lockRotation rootId=rootId}} +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+

{{localize "TOKEN.FIELDS.lockRotation.hint"}}

+
{{localize "TOKEN.RING.SHEET.legend"}} - {{formGroup fields.ring.fields.enabled value=source.ring.enabled rootId=rootId}} - {{formGroup fields.ring.fields.colors.fields.ring value=source.ring.colors.ring rootId=rootId}} - {{formGroup fields.ring.fields.colors.fields.background value=source.ring.colors.background rootId=rootId}} - {{formGroup fields.ring.fields.subject.fields.texture value=source.ring.subject.texture rootId=rootId}} - {{formGroup fields.ring.fields.subject.fields.scale value=source.ring.subject.scale max=3 step=0.02 - rootId=rootId}} - {{formGroup fields.ring.fields.effects value=source.ring.effects input=ringEffectsInput stacked=true - rootId=rootId}} -
--}} +
+ +
+ +
+
+ +
+ +
+ +
+

{{localize "TOKEN.FIELDS.ring.colors.ring.hint"}}

+
+ +
+ +
+ +
+

{{localize "TOKEN.FIELDS.ring.colors.background.hint"}}

+
+ +
+ +
+ + + +
+

{{localize "TOKEN.FIELDS.ring.subject.texture.hint"}}

+
+ +
+ +
+ +
+

{{localize "TOKEN.FIELDS.ring.subject.scale.hint"}}

+
+ {{!--
+ +
+ {{formGroup fields.ring.fields.effects value=source.ring.effects input=ringEffectsInput stacked=true + rootId=rootId}} +
+
--}} +
\ No newline at end of file diff --git a/templates/identity.hbs b/templates/identity.hbs index 8ac9870..806fc4f 100644 --- a/templates/identity.hbs +++ b/templates/identity.hbs @@ -8,10 +8,10 @@
- + {{numberInput fields.x name="x" value="{{object.x}}" id=(concat rootId "-x") placeholder=(localize "Pixels")}} - + {{numberInput fields.y name="y" value="{{object.y}}" id=(concat rootId "-y") placeholder=(localize "Pixels")}}
diff --git a/templates/light.hbs b/templates/light.hbs index 46055d2..3ca865f 100644 --- a/templates/light.hbs +++ b/templates/light.hbs @@ -4,10 +4,10 @@
- + - +
@@ -31,7 +31,7 @@
-

{{ localize 'LIGHT.FIELDS.alpha.hint' }}

From 5baa86e35defeb07c29321abf20b426437d1e712 Mon Sep 17 00:00:00 2001 From: Peterlankton <61578137+Kapuzenjoe@users.noreply.github.com> Date: Fri, 4 Jul 2025 18:04:59 +0200 Subject: [PATCH 6/7] remove new preset naming for DAE compatibility and introduce workaround for changing token names --- src/activeLighting.js | 84 +++++++++++++++++++++--------------------- src/preset-config.js | 8 ++-- templates/header.hbs | 2 +- templates/identity.hbs | 2 +- 4 files changed, 47 insertions(+), 49 deletions(-) diff --git a/src/activeLighting.js b/src/activeLighting.js index 6f627aa..0ddccd2 100644 --- a/src/activeLighting.js +++ b/src/activeLighting.js @@ -8,7 +8,7 @@ class ATL { static init() { let defaultPresets = [ { - label: "torch", + name: "torch", light: { dim: 40, bright: 20, @@ -23,7 +23,7 @@ class ATL { id: "ATLPresetTorch" }, { - label: "lantern", + name: "lantern", light: { dim: 60, bright: 30, @@ -39,7 +39,7 @@ class ATL { }, { - label: "candle", + name: "candle", light: { dim: 10, bright: 2, @@ -55,7 +55,7 @@ class ATL { }, { - label: "flashlight", + name: "flashlight", light: { dim: 60, bright: 30, @@ -91,15 +91,15 @@ class ATL { } static async ready() { - //Update Workaround for change name to label + //Update Workaround let presets = await game.settings.get("ATL", "presets") for (let preset of presets) { - if (!preset.label) { - preset.label = preset.name - delete preset.name + if (!preset.name) { + preset.name = preset.label + delete preset.label } } - + const newTransferral = game.release.generation >= 11 && !CONFIG.ActiveEffect.legacyTransferral; const getEffects = (actor) => { if (!actor) return []; @@ -215,11 +215,11 @@ class ATL { let presetSelector = new foundry.applications.api.DialogV2({ window: { title: "Preset Selector" - }, + }, content: `
- +
`, buttons: [{ action: "update", @@ -245,15 +245,15 @@ class ATL { if (result === "update") { let updatePreset = document.getElementById("presets").value let preset = presets.find(p => p.id === updatePreset) - - new PresetConfig({},preset).render(true); + + new PresetConfig({}, preset).render(true); } else if (result === "copy") { let updatePreset = document.getElementById("presets").value let preset = presets.find(p => p.id === updatePreset) preset = deepClone(preset); delete preset.id; - new PresetConfig({},preset).render(true); + new PresetConfig({}, preset).render(true); } else if (result === "delete") { let preset = document.getElementById("presets").value @@ -277,20 +277,33 @@ class ATL { }); presetSelector.render(true) } - static getSceneControlButtons(buttons) { - let tokenButton = buttons.find(b => b.name == "lighting") - if (tokenButton) { - tokenButton.tools.push({ - name: "atl-lights", + static getSceneControlButtons(controls) { + if (game.release.generation >= 13) { + if (!game.user.isGM) return; + controls.lighting.tools.atlLights = { + name: "atlLights", title: "ATL Presets", icon: "fas fa-plus-circle", - visible: game.user.isGM, - onClick: () => ATL.UpdatePresets(), + onChange: (event, active) => ATL.UpdatePresets(), button: true - }); + }; + } + else { + let tokenButton = controls.find(b => b.name == "lighting") + if (tokenButton) { + tokenButton.tools.push({ + name: "atl-lights", + title: "ATL Presets", + icon: "fas fa-plus-circle", + visible: game.user.isGM, + onClick: () => ATL.UpdatePresets(), + button: true + }); + } } } + static async applyEffects(entity, effects) { if (entity.documentName !== "Actor") return; const tokenArray = entity.getActiveTokens(); @@ -326,7 +339,7 @@ class ATL { if (updateKey === "preset") { // get the matching preset let presetArray = game.settings.get("ATL", "presets") - let preset = presetArray.find(i => i.label === change.value) + let preset = presetArray.find(i => i.name === change.value) if (!preset) { console.error(`ATL: No preset ${change.value} found`) continue; @@ -344,10 +357,11 @@ class ATL { if ("light.angle" in preset) preset["light.angle"] = parseInt(preset["light.angle"]); // remove preset-specific properties delete preset.id - delete preset.label + delete preset.name console.log("ATE | apply preset", change.value, preset); Object.entries(preset) .forEach(([key, value]) => { + if (key === "tokenName") key = "name" //workaround for DAE const originalValue = getProperty(originals, key); applyOverride(key, value, originalValue); }); @@ -542,22 +556,6 @@ class ATL { window.ATLUpdate = ATLUpdate -Hooks.on('init', () => { - ATL.init(); - if (game.release.generation >= 13) { - Hooks.on('getSceneControlButtons', controls => { - if (!game.user.isGM) return; - controls.lighting.tools.atlLights = { - name: "atlLights", - title: "ATL Presets", - icon: "fas fa-plus-circle", - onChange: (event, active) => ATL.UpdatePresets(), - button: true - }; - }); - } - else { - Hooks.on('getSceneControlButtons', ATL.getSceneControlButtons); - } -}); -Hooks.on('ready', ATL.ready); \ No newline at end of file +Hooks.on('init', ATL.init); +Hooks.on('ready', ATL.ready) +Hooks.on('getSceneControlButtons', ATL.getSceneControlButtons) \ No newline at end of file diff --git a/src/preset-config.js b/src/preset-config.js index 719f938..b8a0e9e 100644 --- a/src/preset-config.js +++ b/src/preset-config.js @@ -157,15 +157,15 @@ export class PresetConfig extends HandlebarsApplicationMixin(Application) { for (const key of ["scale", "mirrorX", "mirrorY"]) delete formData.object[key]; // Set default name if creating a new preset with no name - if (this.newMode && !formData.object.label) { + if (this.newMode && !formData.object.name) { const presets = game.settings.get("ATL", "presets"); const count = presets?.length; - formData.object.label = `New Preset (${count + 1})`; - this.fieldsChanged.push("label") + formData.object.name = `New Preset (${count + 1})`; + this.fieldsChanged.push("name") } // Remove name change if updating a preset and trying to clear the name - if (!this.newMode && "label" in formData.object && !formData.object.label) delete formData.object.label; + if (!this.newMode && "name" in formData.object && !formData.object.name) delete formData.object.name; // apply the changes to the original preset Object.entries(formData.object) diff --git a/templates/header.hbs b/templates/header.hbs index 184ad20..f34b6c6 100644 --- a/templates/header.hbs +++ b/templates/header.hbs @@ -1,6 +1,6 @@
- +
\ No newline at end of file diff --git a/templates/identity.hbs b/templates/identity.hbs index 806fc4f..20440f5 100644 --- a/templates/identity.hbs +++ b/templates/identity.hbs @@ -2,7 +2,7 @@
- +
From 8adb0654695b68ff8181b6ff503137a9993e77e5 Mon Sep 17 00:00:00 2001 From: Peterlankton <61578137+Kapuzenjoe@users.noreply.github.com> Date: Tue, 17 Feb 2026 09:29:57 +0100 Subject: [PATCH 7/7] a --- .DS_Store | Bin 6148 -> 8196 bytes .gitignore | 1 + src/activeLighting.js | 2 +- src/preset-config.js | 125 +++++++++++++++++++++++++++++++++++++++--- templates/vision.hbs | 8 +-- 5 files changed, 124 insertions(+), 12 deletions(-) diff --git a/.DS_Store b/.DS_Store index 17106eadb3b5dcd836848f0a0542ed572f5457c5..8fdf0fcfa9f2a4c18c63d1ece852b4a90f951f46 100644 GIT binary patch literal 8196 zcmeHMO=}cE5PhAjaWxPELCDQf$w3fxLB!)2R?wRegnx8 zz>~j16vThw*}Dk7{@9)Bnb}+fS+E+qU(;39_4f5JL-hhMyVGF@*apyMx45~^p`ls3 z?X|WNRxT3_fqo?0Ah>Fu5rF;C&VOR8nEz43!CwwL?3EGiD7&=*OTCv1}r@KaF|eh zn2_0o3dOkW+&^*dFsVl!RRL9?u7IuGTeyxx9OFdR@8;X38`3t)yWM`4_qo=7z192O zzWw=bY#*L#A0L%>1LnKCA~-wCiz7_Ym)U`hkKDcDAvt__`*6mg=2bFT>?Qg5*BjRG z03-CM#Q`RgjoI1XAe+c8xqSWfXvU@DQ!-iPBYBt|r^^|P$zp(Km<%U_te@u@vqLOP zaxmGe*ea>5U;B0Eygw=tKgvsD%^s2#RuY?k6%)L`Aj*v|_e+b+`{Ux{nIs`j=B!(z zeE4betufyTULva=2W?NPcA5Llm3i)H56NJWPt3!8OwN(T0UwMpne^N|dN_dn3uM#a zB{^+%=A0Tm%kwzhGv@b>iTPYi$?BNwDv!&2IX<$h&*LCT^Zl(kO|h*MuGu4|byL6p z_F%NB0?VwxswcN?>;HR;@Bf$iCnz^nKo$5)1x%~E*WKkNp|-AVXKU?*{VBU`*01pB kLO56#yY9+y;`|Ro&XZtE0~Q`>VbhBMCxZ^Ez&};s4<%&>asU7T delta 147 zcmZp1XfcprU|?W$DortDU=RQ@Ie-{MGpJ5X6t-XlGFTZ(8A=#38FCnkQ;L&wlJfI& zK*9`6AOZ+L93Td2Ldb7ST*AJXor6P=8LWgsfE!4=0} + */ + static get DISPLAY_MODES() { + PresetConfig.#DISPLAY_MODES ??= Object.entries(CONST.TOKEN_DISPLAY_MODES).reduce((modes, [key, value]) => { + modes[value] = game.i18n.localize(`TOKEN.DISPLAY_${key}`); + return modes; + }, {}); + return PresetConfig.#DISPLAY_MODES; + } + + static #DISPLAY_MODES; + /** * Localized Token Dispositions * @returns {Record} @@ -134,6 +152,13 @@ export class PresetConfig extends HandlebarsApplicationMixin(Application) { } static #TOKEN_SHAPES; + /* -------------------------------------------- */ + /** + * Maintain a copy of the original to show a real-time preview of changes. + * @type {TokenDocument|PrototypeToken|null} + * @protected + */ + _preview = null; /* -------------------------------------------- */ @@ -207,7 +232,10 @@ export class PresetConfig extends HandlebarsApplicationMixin(Application) { rootId: this.id, object: preset, gridUnits: game.i18n.localize("GridUnits"), + displayModes: PresetConfig.DISPLAY_MODES, visionModes: Object.values(CONFIG.Canvas.visionModes).filter((f) => f.tokenConfig), + detectionModes: Object.values(CONFIG.Canvas.detectionModes).filter(f => f.tokenConfig), + preparedDetectionModes: this.preset?.detectionModes, lightAnimations: Object.entries(CONFIG.Canvas.lightAnimations).reduce( (obj, e) => { obj[e[0]] = game.i18n.localize(e[1].label); @@ -244,6 +272,21 @@ export class PresetConfig extends HandlebarsApplicationMixin(Application) { /* -------------------------------------------- */ + /** + * Mimic changes to the Token document as if they were true document updates. + * @param {object} [changes] The changes to preview. + * @returns {void} + * @protected + */ + _previewChanges(changes) { + if (!changes || !this._preview) return; + const deletions = { "-=actorId": null, "-=actorLink": null }; + const mergeOptions = { inplace: false, performDeletions: true }; + this._preview.updateSource(mergeObject(changes, deletions, mergeOptions)); + } + + /* -------------------------------------------- */ + /** @inheritDoc */ async _preparePartContext(partId, context, options) { context = await super._preparePartContext(partId, context, options); @@ -270,6 +313,74 @@ export class PresetConfig extends HandlebarsApplicationMixin(Application) { console.log(this.fieldsChanged) } + + /* -------------------------------------------- */ + + /** + * Add a new detection mode to the Token preview. + * @this {PresetConfig} + * @type {ApplicationClickAction} + */ + static async #onAddDetectionMode() { + const formData = new FormDataExtended(this.form); + const modes = Object.values(this._processFormData(event, this.form, formData).detectionModes ?? {}); + modes.push({ id: "", range: 0, enabled: true }); + this._previewChanges({ detectionModes: modes }); + await this.render({ parts: ["vision"], resetPreview: false }); + } + + /* -------------------------------------------- */ + + /** + * Remove a detection mode from the Token preview. + * @this {PresetConfig} + * @type {ApplicationClickAction} + */ + static async #onRemoveDetectionMode(_event, target) { + const formData = new FormDataExtended(this.form); + const modes = Object.values(this._processFormData(event, this.form, formData).detectionModes ?? {}); + const index = Number(target.closest("[data-index]")?.dataset.index); + modes.splice(index, 1); + this._previewChanges({ detectionModes: modes }); + await this.render({ parts: ["vision"], resetPreview: false }); + + } + + /** @inheritDoc */ + _processFormData(event, form, formData) { + //const submitData = super._processFormData(event, form, formData); + const submitData = foundry.utils.expandObject(formData.object); + submitData.detectionModes ??= []; // Clear detection modes array + this._processChanges(submitData); + return submitData; + } + + /** + * Process several fields from form submission data into proper model changes. + * @param {object} submitData Form submission data passed through {@link foundry.applications.ux.FormDataExtended} + * @protected + */ + _processChanges(submitData) { + // Convert scale and mirror data from the form submission to TextureData changes + // if (typeof submitData.scale === "number") { + // submitData.texture.scaleX = submitData.scale * (submitData.mirrorX ? -1 : 1); + // submitData.texture.scaleY = submitData.scale * (submitData.mirrorY ? -1 : 1); + // } + // for (const key of ["scale", "mirrorX", "mirrorY"]) delete submitData[key]; + + // // Process token ring effects from the form submission + // if (Array.isArray(submitData.ring?.effects)) { + // const TRE = CONFIG.Token.ring.ringClass.effects; + // let effects = submitData.ring.enabled ? TRE.ENABLED : TRE.DISABLED; + // for (const effectName of submitData.ring.effects) { + // const v = TRE[effectName] ?? 0; + // effects |= v; + // } + // submitData.ring.effects = effects; + // } + } + + _clearProperty(object, key) { let target = object; let cleared = false; diff --git a/templates/vision.hbs b/templates/vision.hbs index 2aa6b93..8383384 100644 --- a/templates/vision.hbs +++ b/templates/vision.hbs @@ -32,7 +32,7 @@
- {{!--
+
{{localize "TOKEN.SightHeaderDetection"}}
{{localize "TOKEN.DetectionMode"}}
@@ -63,7 +63,7 @@
{{/each}} - {{#each sourceDetectionModes as |mode i|}} + {{!-- {{#each sourceDetectionModes as |mode i|}}