diff --git a/changelog.md b/changelog.md index 6d7799d3..d13c02ec 100644 --- a/changelog.md +++ b/changelog.md @@ -1,4 +1,7 @@ # v11.0 +## v11.1.3 - Werther de Zloth l'Onirique +- Fix: dans les TMRs, les tooltips affichent bien les informations de tous les effets sur la case + ## v11.1.2 - Les vertèbres de Werther de Zloth - Fix: les jets d'encaissement fonctionnent de nouveau normalement - Macro "Mon personnage" permettant au joueur d'accéder à sa feuille de personnage depuis la barre de macros diff --git a/module/rdd-tmr-dialog.js b/module/rdd-tmr-dialog.js index 78280820..1080f6f5 100644 --- a/module/rdd-tmr-dialog.js +++ b/module/rdd-tmr-dialog.js @@ -62,8 +62,8 @@ export class RdDTMRDialog extends Dialog { this.loadCasesSpeciales(); this.allTokens = []; this.rencontreState = 'aucune'; - this.pixiApp = new PIXI.Application({ width: 720, height: 860 }); - this.pixiTMR = new PixiTMR(this, this.pixiApp); + this.pixiTMR = new PixiTMR(this); + this.subdialog = undefined this.callbacksOnAnimate = []; @@ -128,7 +128,7 @@ export class RdDTMRDialog extends Dialog { /* -------------------------------------------- */ createPixiSprites() { - EffetsDraconiques.carteTmr.createSprite(this.pixiTMR); + this.pixiTMR.setup() this.updateTokens(); this.forceDemiRevePositionView(); } @@ -139,13 +139,9 @@ export class RdDTMRDialog extends Dialog { this.demiReve = this._tokenDemiReve(); this._trackToken(this.demiReve); } - let tokens = this._getTokensCasesTmr() - .concat(this._getTokensRencontres()) - .concat(this._getTokensSortsReserve()); - - for (let t of tokens) { - this._trackToken(t); - } + this._getTokensCasesTmr().forEach(t => this._trackToken(t)) + this._getTokensRencontres().forEach(t => this._trackToken(t)) + this._getTokensSortsReserve().forEach(t => this._trackToken(t)) } /* -------------------------------------------- */ @@ -204,6 +200,7 @@ export class RdDTMRDialog extends Dialog { if (this.subdialog) { return this.forceTMRContinueAction(); } + let oddq = TMRUtility.coordTMRToOddq(this._getActorCoord()); if (move == 'top') oddq.row -= 1; @@ -230,7 +227,8 @@ export class RdDTMRDialog extends Dialog { document.getElementsByClassName("tmr-row") .item(0) - .insertCell(0).append(this.pixiApp.view); + .insertCell(0) + .append(this.pixiTMR.view); if (this.viewOnly) { this.html.find('.lancer-sort').remove(); @@ -241,24 +239,17 @@ export class RdDTMRDialog extends Dialog { HtmlUtility.showControlWhen(this.html.find(".appliquerFatigue"), ReglesOptionnelles.isUsing("appliquer-fatigue")); HtmlUtility.showControlWhen(this.html.find(".lire-signe-draconique"), this.actor.isResonanceSigneDraconique(this._getActorCoord())); - this.html.find('tr.tmr-row *').click((event) => { - this.subdialog?.bringToTop(); - }); + this.html.find('tr.tmr-row *').click(event => this.subdialog?.bringToTop()); // Roll Sort - this.html.find('.lancer-sort').click((event) => { - this.actor.rollUnSort(this._getActorCoord()); - }); - this.html.find('.lire-signe-draconique').click((event) => { - this.actor.rollLireSigneDraconique(this._getActorCoord()); - }); - - this.html.find('#dir-top').click((event) => this.moveFromKey("top")); - this.html.find('#dir-top-left').click((event) => this.moveFromKey("top-left")); - this.html.find('#dir-top-right').click((event) => this.moveFromKey("top-right")); - this.html.find('#dir-bottom-left').click((event) => this.moveFromKey("bottom-left")); - this.html.find('#dir-bottom-right').click((event) => this.moveFromKey("bottom-right")); - this.html.find('#dir-bottom').click((event) => this.moveFromKey("bottom")); + this.html.find('.lancer-sort').click(event => this.actor.rollUnSort(this._getActorCoord())); + this.html.find('.lire-signe-draconique').click(event => this.actor.rollLireSigneDraconique(this._getActorCoord())); + this.html.find('#dir-top').click(event=> this.moveFromKey("top")); + this.html.find('#dir-top-left').click(event=> this.moveFromKey("top-left")); + this.html.find('#dir-top-right').click(event=> this.moveFromKey("top-right")); + this.html.find('#dir-bottom-left').click(event=> this.moveFromKey("bottom-left")); + this.html.find('#dir-bottom-right').click(event=> this.moveFromKey("bottom-right")); + this.html.find('#dir-bottom').click(event=> this.moveFromKey("bottom")); // Gestion du cout de montée en points de rêve let reveCout = ((this.tmrdata.isRapide && !EffetsDraconiques.isDeplacementAccelere(this.actor)) ? -2 : -1) - this.actor.countMonteeLaborieuse(); @@ -382,19 +373,8 @@ export class RdDTMRDialog extends Dialog { /* -------------------------------------------- */ $marquerCasesTMR(listCoordTMR) { - this.currentRencontre.graphics = []; // Keep track of rectangles to delete it this.currentRencontre.locList = duplicate(listCoordTMR); // And track of allowed location - for (let coordTMR of listCoordTMR) { - const rect = this._getCaseRectangleCoord(coordTMR); - const rectDraw = new PIXI.Graphics(); - rectDraw.beginFill(0xffff00, 0.3); - // set the line style to have a width of 5 and set the color to red - rectDraw.lineStyle(5, 0xff0000); - // draw a rectangle - rectDraw.drawRect(rect.x, rect.y, rect.w, rect.h); - this.pixiApp.stage.addChild(rectDraw); - this.currentRencontre.graphics.push(rectDraw); // garder les objets pour gestion post-click - } + this.currentRencontre.graphics = listCoordTMR.map(coordTMR => this.pixiTMR.addMarkTMR(coordTMR)) } /* -------------------------------------------- */ @@ -907,15 +887,11 @@ export class RdDTMRDialog extends Dialog { /* -------------------------------------------- */ nettoyerRencontre() { - if (!this.currentRencontre) return; // Sanity check - if (this.currentRencontre.graphics) { - for (let drawRect of this.currentRencontre.graphics) { - // Suppression des dessins des zones possibles - this.pixiApp.stage.removeChild(drawRect); - } - } - this.currentRencontre = undefined; // Nettoyage de la structure - this.rencontreState = 'aucune'; // Et de l'état + // Suppression des dessins des zones possibles + this.currentRencontre?.graphics?.forEach(graphic => this.pixiTMR.removeGraphic(graphic)) + // Nettoyage de la structureet de l'état + this.currentRencontre = undefined; + this.rencontreState = 'aucune'; } /* -------------------------------------------- */ @@ -1106,18 +1082,10 @@ export class RdDTMRDialog extends Dialog { await this.postRencontre(tmr); return tmr; } - /* -------------------------------------------- */ - /** Retourne les coordonnées x, h, w, h du rectangle d'une case donnée */ - _getCaseRectangleCoord(coord) { - return this.pixiTMR.getCaseRectangle(TMRUtility.coordTMRToOddq(coord)); - } /* -------------------------------------------- */ _removeTokens(filter) { - const tokensToRemove = this.allTokens.filter(filter); - for (let token of tokensToRemove) { - this.pixiApp.stage.removeChild(token.sprite); - } + this.allTokens.filter(filter).forEach(token => this.pixiTMR.removeToken(token)) } /* -------------------------------------------- */ @@ -1125,7 +1093,9 @@ export class RdDTMRDialog extends Dialog { if (this.demiReve === token && this.isDemiReveCache()) { return; } - this.pixiTMR.setPosition(token.sprite, TMRUtility.coordTMRToOddq(token.coordTMR())); - this.allTokens.push(token); + this.pixiTMR.positionToken(token); + if (!this.allTokens.includes(token)) { + this.allTokens.push(token); + } } } diff --git a/module/tmr/carte-tmr.js b/module/tmr/carte-tmr.js index b1e61053..dfdec720 100644 --- a/module/tmr/carte-tmr.js +++ b/module/tmr/carte-tmr.js @@ -1,3 +1,4 @@ +import { TMRUtility } from "../tmr-utility.js"; import { Draconique } from "./draconique.js"; import { PixiTMR } from "./pixi-tmr.js"; @@ -16,7 +17,6 @@ export class CarteTmr extends Draconique { img() { return 'systems/foundryvtt-reve-de-dragon/styles/img/ui/tmr.webp' } createSprite(pixiTMR) { - const img = PixiTMR.getImgFromCode(this.code()) const sprite = new PIXI.Sprite(PIXI.utils.TextureCache[img]); // Setup the position of the TMR @@ -28,10 +28,12 @@ export class CarteTmr extends Draconique { sprite.anchor.set(0); sprite.buttonMode = true; sprite.tmrObject = pixiTMR; - - pixiTMR.addTooltip(sprite, (e,s) => this.computeTooltip(e,s)); - pixiTMR.pixiApp.stage.addChild(sprite); return sprite; } + computeTooltip(coordTMR) { + const tmr = TMRUtility.getTMR(coordTMR) + return tmr? TMRUtility.getTMRLabel(coordTMR) : ''; + } + } diff --git a/module/tmr/draconique.js b/module/tmr/draconique.js index dea066dd..7095321a 100644 --- a/module/tmr/draconique.js +++ b/module/tmr/draconique.js @@ -86,15 +86,13 @@ export class Draconique { * @param {*} pixiTMR instance de PixiTMR qui gère les tooltips, les méthodes de création de sprite standard, les clicks. */ token(pixiTMR, linkData, coordTMR, type = undefined) { + const tooltip = this.tooltip(linkData); const token = { sprite: this.createSprite(pixiTMR), - coordTMR: coordTMR + coordTMR: coordTMR, + tooltip: tooltip }; token[type ?? this.code()] = linkData; - this.linkData = linkData; - if (this.tooltip(linkData)) { - pixiTMR.addTooltip(token.sprite, (e, s) => this.computeTooltip(e, s)); - } return token; } diff --git a/module/tmr/pixi-tmr.js b/module/tmr/pixi-tmr.js index 213dabf8..08b6f2b8 100644 --- a/module/tmr/pixi-tmr.js +++ b/module/tmr/pixi-tmr.js @@ -1,6 +1,8 @@ +import { Misc } from "../misc.js"; import { RdDTMRDialog } from "../rdd-tmr-dialog.js"; import { tmrConstants, tmrTokenZIndex } from "../tmr-constants.js"; import { TMRUtility } from "../tmr-utility.js"; +import { EffetsDraconiques } from "./effets-draconiques.js"; export const tooltipStyle = new PIXI.TextStyle({ fontFamily: 'CaslonAntique', @@ -15,11 +17,33 @@ export class PixiTMR { static textures = [] - constructor(tmrObject, pixiApp) { - this.tmrObject = tmrObject; - this.pixiApp = pixiApp ?? tmrObject.pixiApp; - this.pixiApp.stage.sortableChildren = true; + constructor(tmrDialog) { + this.tmrDialog = tmrDialog; + this.callbacksOnAnimate = []; + + this.pixiApp = new PIXI.Application({ width: 720, height: 860 }); + this.pixiApp.eventMode = 'static'; + this.pixiApp.stage.sortableChildren = true; + this.tooltip = new PIXI.Text('', tooltipStyle); + this.pixiApp.stage.addChild(this.tooltip); + + } + + get view() { + return this.pixiApp.view + } + + setup() { + this.carteTMR = EffetsDraconiques.carteTmr.createSprite(this); + this.pixiApp.stage.addChild(this.carteTMR); + this.carteTMR.isOver = false; + this.carteTMR.eventMode = 'static'; + this.carteTMR + .on('pointermove', event => this.onPointerMove(event)) + .on('pointerdown', event => this.onClickBackground(event)) + .on('pointerover', event => this.onShowTooltip(event)) + .on('pointerout', event => this.onHideTooltip(event)); } async load(onLoad = (loader, resources) => { }) { @@ -46,6 +70,22 @@ export class PixiTMR { this.callbacksOnAnimate.push(() => animation(this.pixiApp)); } + addMarkTMR(coordTMR) { + const rect = this.getCaseRectangle(TMRUtility.coordTMRToOddq(coordTMR)) + const markTMR = new PIXI.Graphics(); + markTMR.beginFill(0xffff00, 0.3); + // set the line style to have a width of 5 and set the color to red + markTMR.lineStyle(5, 0xff0000); + // draw a rectangle + markTMR.drawRect(rect.x, rect.y, rect.w, rect.h); + this.pixiApp.stage.addChild(markTMR); + return markTMR + } + + removeGraphic(graphic) { + this.pixiApp.stage.removeChild(graphic); + } + sprite(code, options = {}) { let img = PixiTMR.getImgFromCode(code) const texture = PIXI.utils.TextureCache[img]; @@ -67,7 +107,7 @@ export class PixiTMR { return sprite; } - circle(name, options = {}) { + circle(code, options = {}) { let sprite = new PIXI.Graphics(); sprite.beginFill(options.color, options.opacity); sprite.drawCircle(0, 0, (options.taille ?? 12) / 2); @@ -77,63 +117,76 @@ export class PixiTMR { return sprite; } - addTooltip(sprite, computeTooltip) { - sprite.tooltip = new PIXI.Text('', tooltipStyle); - sprite.tooltip.zIndex = tmrTokenZIndex.tooltip; - sprite.isOver = false; - sprite.eventMode = 'static'; - sprite - .on('pointermove', event => this.onPointerMove(event, sprite, computeTooltip)) - .on('pointerdown', event => this.onClickBackground(event)) - .on('pointerover', event => this.onShowTooltip(event, sprite)) - .on('pointerout', event => this.onHideTooltip(event, sprite)); - } - onClickBackground(event) { if (!this.viewOnly) { - this.tmrObject.onClickTMR(event) + this.tmrDialog.onClickTMR(event) } } - onPointerMove(event, sprite, computeTooltip) { - if (sprite.isOver && sprite.tooltip) { - var { x, y } = TMRUtility.computeEventPosition(event); - const oddq = TMRUtility.computeOddq(x, y); + onPointerMove(event) { + if (this.carteTMR.isOver) { + this.setTooltipPosition(event); + this.tooltip.text = this.computeTooltip(event); + } + } + + onShowTooltip(event) { + if (!this.carteTMR.isOver) { + this.setTooltipPosition(event); + this.pixiApp.stage.addChild(this.tooltip); + this.tooltip.text = this.computeTooltip(event); + } + this.carteTMR.isOver = true; + } - sprite.tooltip.x = x + (oddq.col > 8 ? - 3 * tmrConstants.full : tmrConstants.half) - sprite.tooltip.y = y + (oddq.row > 10 ? - tmrConstants.half : tmrConstants.half) - sprite.tooltip.text = computeTooltip(event, sprite); + onHideTooltip(event) { + if (this.carteTMR.isOver) { + this.pixiApp.stage.removeChild(this.tooltip); + } + this.carteTMR.isOver = false; + } + + computeTooltip(event) { + const oddq = TMRUtility.computeEventOddq(event); + const coordTMR = TMRUtility.oddqToCoordTMR(oddq); + const tmr = TMRUtility.getTMR(coordTMR) + if (tmr) { + const labelTMR = TMRUtility.getTMRLabel(coordTMR); + const tokenTooltips = this.tmrDialog.allTokens + .filter(token => token.coordTMR() == coordTMR) + .map(token => token.tooltip); + const tmrTooltip = `${coordTMR}: ${labelTMR}`; + return [tmrTooltip, ...tokenTooltips].reduce(Misc.joining('\n')) } } - onShowTooltip(event, sprite) { - if (sprite.tooltip) { - if (!sprite.isOver) { - sprite.tooltip.x = sprite.x; - sprite.tooltip.y = sprite.y; - this.pixiApp.stage.addChild(sprite.tooltip); - } - sprite.isOver = true; + setTooltipPosition(event) { + var { x, y } = TMRUtility.computeEventPosition(event); + const oddq = TMRUtility.computeOddq(x, y); + + this.tooltip.x = x + (oddq.col > 8 ? -3 * tmrConstants.full : tmrConstants.half); + this.tooltip.y = y + (oddq.row > 10 ? -tmrConstants.half : tmrConstants.half); + } + + positionToken(token) { + if (token.sprite) { + const sprite = token.sprite; + const oddq = TMRUtility.coordTMRToOddq(token.coordTMR()); + + const decallagePairImpair = (oddq.col % 2 == 0) ? tmrConstants.col1_y : tmrConstants.col2_y; + const dx = (sprite.decallage == undefined) ? 0 : sprite.decallage.x; + const dy = (sprite.decallage == undefined) ? 0 : sprite.decallage.y; + sprite.x = tmrConstants.gridx + (oddq.col * tmrConstants.cellw) + dx; + sprite.y = tmrConstants.gridy + (oddq.row * tmrConstants.cellh) + dy + decallagePairImpair; } } - onHideTooltip(event, sprite) { - if (sprite.tooltip) { - if (sprite.isOver) { - this.pixiApp.stage.removeChild(sprite.tooltip); - } - sprite.isOver = false; + removeToken(token) { + if (token.sprite) { + this.pixiApp.stage.removeChild(token.sprite) } } - setPosition(sprite, oddq) { - let decallagePairImpair = (oddq.col % 2 == 0) ? tmrConstants.col1_y : tmrConstants.col2_y; - let dx = (sprite.decallage == undefined) ? 0 : sprite.decallage.x; - let dy = (sprite.decallage == undefined) ? 0 : sprite.decallage.y; - sprite.x = tmrConstants.gridx + (oddq.col * tmrConstants.cellw) + dx; - sprite.y = tmrConstants.gridy + (oddq.row * tmrConstants.cellh) + dy + decallagePairImpair; - } - getCaseRectangle(oddq) { let decallagePairImpair = (oddq.col % 2 == 0) ? tmrConstants.col1_y : tmrConstants.col2_y; let x = tmrConstants.gridx + (oddq.col * tmrConstants.cellw) - (tmrConstants.cellw / 2);