From a42accc7ecbb29dcb0c2bf2beb9618d86c60fe1b Mon Sep 17 00:00:00 2001 From: macniel Date: Mon, 13 Jul 2026 21:35:30 +0200 Subject: [PATCH] implements #84 in two distinct ways: left click for a touch friendly dialog, right click for inline editing of a resource. --- src/lang/de.json | 14 +++ src/module/data/character.mjs | 14 +++ src/module/dialog/resourceDialog.mjs | 113 +++++++++++++++++++ src/module/sheets/characterSheet.mjs | 87 +++++++++++++- src/style/atoms/_colours.scss | 2 + src/style/molecules/_sidebar-elements.scss | 29 ++++- src/style/organisms/_resource-dialog.scss | 42 +++++++ src/style/styles.scss | 1 + src/system.json | 4 +- src/templates/actor/character/main-sheet.hbs | 16 +-- src/templates/dialog/resource-dialog.hbs | 5 + 11 files changed, 315 insertions(+), 12 deletions(-) create mode 100644 src/module/dialog/resourceDialog.mjs create mode 100644 src/style/organisms/_resource-dialog.scss create mode 100644 src/templates/dialog/resource-dialog.hbs diff --git a/src/lang/de.json b/src/lang/de.json index 7c84a0e8..98a53114 100644 --- a/src/lang/de.json +++ b/src/lang/de.json @@ -55,5 +55,19 @@ }, "ITEM_BROWSER": { "progress": "{current}/{max}: Importiere von {compendium}" + }, + "RESOURCE_DIALOG": { + "Lep": { + "title": "Lebenspunkte anpassen" + }, + "Aup": { + "title": "Ausdauerpunkte anpassen" + }, + "Asp": { + "title": "Astralpunkte anpassen" + }, + "Kap": { + "title": "Karmapunkte anpassen" + } } } diff --git a/src/module/data/character.mjs b/src/module/data/character.mjs index c571c246..9b127d60 100644 --- a/src/module/data/character.mjs +++ b/src/module/data/character.mjs @@ -8,6 +8,20 @@ const { ArrayField, } = foundry.data.fields; +/** + * + * @property LE + * @property AU + * @property AE + * @property KE + */ +export const ResourceType = { + LE: "Lep", + AU: "Aup", + AE: "Asp", + KE: "Kap" +} + export class PlayerCharacterDataModel extends foundry.abstract.TypeDataModel { static defineSchema() { diff --git a/src/module/dialog/resourceDialog.mjs b/src/module/dialog/resourceDialog.mjs new file mode 100644 index 00000000..c9717873 --- /dev/null +++ b/src/module/dialog/resourceDialog.mjs @@ -0,0 +1,113 @@ +import {ResourceType} from "../data/character.mjs"; + +const { + ApplicationV2, + HandlebarsApplicationMixin +} = foundry.applications.api + +export class EditResourceDialog extends HandlebarsApplicationMixin(ApplicationV2) { + static DEFAULT_OPTIONS = { + classes: ['dsa41', 'dialog', 'resource'], + tag: "form", + position: { + width: 480, + height: 480 + }, + window: { + resizable: false, + title: "Resource anpassen" + }, + form: { + submitOnChange: false, + closeOnSubmit: false, + handler: EditResourceDialog.#onSubmitForm + }, + actions: { + setResource: EditResourceDialog.#onSetResource, + } + } + + static PARTS = { + form: { + template: 'systems/DSA_4-1/templates/dialog/resource-dialog.hbs', + } + } + + _actor = null; + _resourceType = null; + _min = 0; + _current = 0; + _max = 0; + + constructor(actor, resourceType, min, current, max) { + super(); + this._actor = actor; + this._resourceType = resourceType; + this._min = min; + this._current = current; + this._max = max; + } + + static async #onSubmitForm(event, form, formData) { + event.preventDefault() + this.close() + } + + static async #onSetResource(event, target) { + const {value} = target.dataset; + switch(this._resourceType) { + case ResourceType.LE: + await this._actor.update({"system.lep.aktuell": value}); + break; + case ResourceType.AU: + await this._actor.update({"system.aup.aktuell": value}); + break; + case ResourceType.AE: + await this._actor.update({"system.asp.aktuell": value}); + break; + case ResourceType.KE: + await this._actor.update({"system.kap.aktuell": value}); + } + this.close(); + } + + async _prepareContext(options) { + const context = await super._prepareContext(options) + + context.steps = []; + + for (let i = this._min; i <= this._max; ++i ) { + if (i < this._current) { + context.steps.push({ + display: i - this._current, + value: i, + isReduction: true, + isIncreasing: false, + }); + } else if (i === this._current) { + context.steps.push({ + display: i - this._current, + value: i, + isReduction: false, + isIncreasing: false, + }); + } else { + context.steps.push({ + display: "+" + (i - this._current), + value: i, + isReduction: false, + isIncreasing: true, + }); + } + } + return context + } + + _configureRenderOptions(options) { + super._configureRenderOptions(options) + if (options.window) { + options.window.title = game.i18n.format("RESOURCE_DIALOG." + this._resourceType + ".title") + } + return options + } +} diff --git a/src/module/sheets/characterSheet.mjs b/src/module/sheets/characterSheet.mjs index 6cf3a150..6df735c9 100644 --- a/src/module/sheets/characterSheet.mjs +++ b/src/module/sheets/characterSheet.mjs @@ -24,6 +24,8 @@ import {StandaloneLiturgies} from "./character-standalone/liturgies.mjs"; import {StandaloneHealth} from "./character-standalone/health.mjs"; import {SpellDialog} from "../dialog/spellDialog.mjs"; import {displayRoll} from "../globals/displayRoll.js"; +import {ResourceType} from "../data/character.mjs"; +import {EditResourceDialog} from "../dialog/resourceDialog.mjs"; const {HandlebarsApplicationMixin, DocumentSheetV2} = foundry.applications.api const {ActorSheetV2} = foundry.applications.sheets @@ -76,7 +78,10 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { setWounds: CharacterSheet.#setWounds, switchSet: CharacterSheet.#switchSet, openInitiative: CharacterSheet.#openInitiative, - + editLep: CharacterSheet.#editLep, + editAup: CharacterSheet.#editAup, + editAsp: CharacterSheet.#editAsp, + editKap: CharacterSheet.#editKap, } } @@ -272,6 +277,59 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { new SpellDialog(this.document, itemId).render(true) } + static #editAup(event, target, isRightClicked) { + + if (!isRightClicked) { + const min = 0 + const current = this.document.system.aup.aktuell + const max = this.document.system.aup.max + + const dialog = new EditResourceDialog(this.document, ResourceType.AU, min, current, max) + dialog.render(true) + target.parentElement.querySelector('input').blur(); + } + } + + static #editLep(event, target, isRightClicked) { + + if (!isRightClicked) { + const min = 0 + const current = this.document.system.lep.aktuell + const max = this.document.system.lep.max + + const dialog = new EditResourceDialog(this.document, ResourceType.LE, min, current, max) + dialog.render(true) + target.parentElement.querySelector('input').blur(); + } + } + + static #editAsp(event, target, isRightClicked) { + + if (!isRightClicked) { + const min = 0 + + const current = this.document.system.asp.aktuell + const max = this.document.system.asp.max + + const dialog = new EditResourceDialog(this.document, ResourceType.AE, min, current, max) + dialog.render(true) + target.parentElement.querySelector('input').blur(); + } + } + + static #editKap(event, target, isRightClicked) { + + if (!isRightClicked) { + const min = 0 + const current = this.document.system.kap.aktuell + const max = this.document.system.kap.max + + const dialog = new EditResourceDialog(this.document, ResourceType.KE, min, current, max) + dialog.render(true) + target.parentElement.querySelector('input').blur(); + } + } + static #startResting(event, target) { const dialog = new RestingDialog(this.document) @@ -374,6 +432,22 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { static async #onSubmitForm(event, form, formData) { event.preventDefault() + if (formData.object["system.lep.aktuell"]?.[1]) { + formData.object["system.lep.aktuell"] = formData.object["system.lep.aktuell"][0] + } + + if (formData.object["system.aup.aktuell"]?.[1]) { + formData.object["system.aup.aktuell"] = formData.object["system.aup.aktuell"][0] + } + + if (formData.object["system.asp.aktuell"]?.[1]) { + formData.object["system.asp.aktuell"] = formData.object["system.asp.aktuell"][0] + } + + if (formData.object["system.kap.aktuell"]?.[1]) { + formData.object["system.kap.aktuell"] = formData.object["system.kap.aktuell"][0] + } + await this.document.update(formData.object) return false @@ -797,6 +871,17 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { } } + async _postRender() { + this.element.querySelectorAll('.sidebar-element.resource-bar[data-action]').forEach( e => { + const { action} = e.dataset; + e.addEventListener('contextmenu', (event) => { + if (CharacterSheet.DEFAULT_OPTIONS.actions[action]) { + CharacterSheet.DEFAULT_OPTIONS.actions[action].bind(this)(event, event.target, true); + } + }) + }) + } + } export default CharacterSheet diff --git a/src/style/atoms/_colours.scss b/src/style/atoms/_colours.scss index 774e4429..8ebd247c 100644 --- a/src/style/atoms/_colours.scss +++ b/src/style/atoms/_colours.scss @@ -22,6 +22,8 @@ $talent-language-text-color: #000; $talent-crafting-color: #cd9551; $talent-crafting-text-color: #000; +$help-fill-color: #60d060ff; +$help-border-color: #308030ff; $harm-fill-color: #ff0000ff; $harm-border-color: #3c0000ff; diff --git a/src/style/molecules/_sidebar-elements.scss b/src/style/molecules/_sidebar-elements.scss index f8a5ba5c..e5e2ec84 100644 --- a/src/style/molecules/_sidebar-elements.scss +++ b/src/style/molecules/_sidebar-elements.scss @@ -8,6 +8,8 @@ .resource-bar { + cursor: pointer; + height: 24px; width: 100%; position: relative; @@ -16,18 +18,43 @@ margin: 8px 0; label { + + cursor: pointer; position: absolute; left: 0; top: 0; bottom: 0; z-index: 3; + width: 40px; line-height: 24px; vertical-align: middle; text-indent: 8px; color: white; text-shadow: 2px 2px 1px rgba(0, 0, 0, 0.3); - } + + } + input { + position: absolute; + left: 40px; + top: 0; + width: calc(100% - 40px); + z-index: 4; + height: 22px; + padding: 0; + margin: 0; + line-height: 24px; + vertical-align: middle; + text-indent: 8px; + color: white; + font-size: large; + background: transparent; + text-shadow: 2px 2px 1px rgba(0, 0, 0, 0.3); + border: 0; + &:hover { + background-color: rgba(0, 0, 0, 0.5); + } + } span.resource-fill { position: absolute; left: 0; diff --git a/src/style/organisms/_resource-dialog.scss b/src/style/organisms/_resource-dialog.scss new file mode 100644 index 00000000..200c3784 --- /dev/null +++ b/src/style/organisms/_resource-dialog.scss @@ -0,0 +1,42 @@ +@use "../atoms/colours" as colour; + +.dsa41.dialog.resource { + + section.steps { + overflow: auto; + flex: 1; + display: grid; + grid-template-columns: repeat(5, 1fr); + + .step { + display: inline-block; + border: 1px solid black; + width: 64px; + height: 48px; + line-height: 48px; + vertical-align: middle; + text-align: center; + justify-self: center; + font-weight: bold; + cursor: pointer; + + margin: 4px; + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.5), + 2px 2px inset rgba(0, 0, 0, 0.2); + + &.reducing { + background-color: colour.$harm-fill-color; + border-color: colour.$harm-border-color; + background-blend-mode: hue; + } + + &.increasing { + background-color: colour.$help-fill-color; + border-color: colour.$help-border-color; + background-blend-mode: hue; + } + } + + } + +} diff --git a/src/style/styles.scss b/src/style/styles.scss index fa9bdc0a..5274d255 100644 --- a/src/style/styles.scss +++ b/src/style/styles.scss @@ -39,4 +39,5 @@ @use "organisms/dialog"; @use "organisms/deity-sheet"; @use "organisms/item-browser-dialog"; +@use "organisms/resource-dialog"; @use "atoms/chat"; \ No newline at end of file diff --git a/src/system.json b/src/system.json index 89c4f26a..21932c0f 100644 --- a/src/system.json +++ b/src/system.json @@ -2,7 +2,7 @@ "id": "DSA_4-1", "title": "Das Schwarze Auge 4.1", "description": "Noch ein Spielsystem für Das Schwarze Auge 4.1", - "version": "0.11.2", + "version": "0.0.1", "compatibility": { "minimum": 12, "verified": 13 @@ -364,5 +364,5 @@ "primaryTokenAttribute": "lep.aktuell", "url": "https://git.macniel.online/macniel/foundry-dsa41-game", "manifest": "https://git.macniel.online/macniel/foundry-dsa41-game/raw/branch/main/src/system.json", - "download": "https://git.macniel.online/macniel/foundry-dsa41-game/releases/download/0.11.2/release.zip" + "download": "https://git.macniel.online/macniel/foundry-dsa41-game/releases/download/0.0.1/release.zip" } diff --git a/src/templates/actor/character/main-sheet.hbs b/src/templates/actor/character/main-sheet.hbs index 798e5c2e..2389e217 100644 --- a/src/templates/actor/character/main-sheet.hbs +++ b/src/templates/actor/character/main-sheet.hbs @@ -31,27 +31,27 @@ - {{#if ausdauer}} - {{/if}} {{#if this.hasLiturgies}} -