From ed890a35c3cfabfef6679ed4296328c8025c4bef Mon Sep 17 00:00:00 2001 From: Brian Fertig Date: Sun, 6 Sep 2026 09:28:22 -0600 Subject: [PATCH] Fix text centering and close-button click passthrough in UI windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Center the ✕ close glyph and "IN PROGRESS" labels via setOrigin(0.5, …); Phaser Text defaults to origin (0,0), so they were anchored top-left and sat off-center on their plates - Widen detail buttons from 152 to 190 px so the widest label ("IN PROGRESS 88%") no longer bleeds past the plate edges - Treat 'closing' as open in isOpen so a close tap is consumed by the window while it fades out, instead of leaking through as a world click --- js/ui/BuildWindow.js | 16 +++++++++++++--- js/ui/ResearchWindow.js | 17 ++++++++++++++--- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/js/ui/BuildWindow.js b/js/ui/BuildWindow.js index 7609809..1ebf4ec 100644 --- a/js/ui/BuildWindow.js +++ b/js/ui/BuildWindow.js @@ -298,12 +298,15 @@ export class BuildWindow extends Phaser.GameObjects.Container { const cy = rect.y + titleH / 2 - 2; this.closeBtn = { x: cx, y: cy, w: cw, h: cw, hover: false }; this.closeG = G(2); - this.closeTxt = T(cx, cy - 5, '✕', { + this.closeTxt = T(cx, cy + 1, '✕', { fontFamily: BODY, fontSize: '15px', color: toCss(C.neon2), align: 'center', }, 2); + // Text's default origin is (0,0) — without this the ✕ anchors its + // top-left at the plate centre and sits right-of-centre. + this.closeTxt.setOrigin(0.5, 0.5); const closeRect = new Phaser.Geom.Rectangle(cx - cw / 2, cy - cw / 2, cw, cw); this.closeG.setInteractive({ useHandCursor: true, @@ -915,7 +918,9 @@ export class BuildWindow extends Phaser.GameObjects.Container { }) .setScrollFactor(0); cont.add(this.dCost); - const btnW = 152; + // 190: the widest label is "IN PROGRESS 88%" (~166 px at 13px/ls-3) — + // 152 let it bleed past the plate edges. + const btnW = 190; const wrapW = Math.max(120, rightX + rightW - 12 - btnW - 18 - tx); this.dDesc = s .text(tx, detailY + 80, '', { @@ -944,6 +949,7 @@ export class BuildWindow extends Phaser.GameObjects.Container { letterSpacing: 3, align: 'center', }) + .setOrigin(0.5, 0) // centre on the plate — text's default origin is (0,0) .setScrollFactor(0); const bar = s.graphics().setScrollFactor(0); cont.add([g, label, bar]); @@ -1250,8 +1256,12 @@ export class BuildWindow extends Phaser.GameObjects.Container { }); } + // 'closing' counts as open: the close button flips openState in the + // SAME input pass, before the scene's pointerdown guard runs — while + // the window is still on screen (fading out) it must keep owning the + // click, or the close tap leaks through as a world click. get isOpen() { - return this.openState === 'open' || this.openState === 'opening'; + return this.openState === 'open' || this.openState === 'opening' || this.openState === 'closing'; } /** Repaint everything from state (after a build starts / completes). */ diff --git a/js/ui/ResearchWindow.js b/js/ui/ResearchWindow.js index 3a55786..b7431f3 100644 --- a/js/ui/ResearchWindow.js +++ b/js/ui/ResearchWindow.js @@ -271,12 +271,15 @@ export class ResearchWindow extends Phaser.GameObjects.Container { const cy = rect.y + titleH / 2 - 2; this.closeBtn = { x: cx, y: cy, w: cw, h: cw, hover: false }; this.closeG = G(2); - this.closeTxt = T(cx, cy - 5, '✕', { + this.closeTxt = T(cx, cy + 1, '✕', { fontFamily: BODY, fontSize: '15px', color: toCss(C.neon2), align: 'center', }, 2); + // Text's default origin is (0,0) — without this the ✕ anchors its + // top-left at the plate centre and sits right-of-centre. + this.closeTxt.setOrigin(0.5, 0.5); // v4: setInteractive takes a config object — a bare shape (or the // 4-arg Phaser-3 form) leaves input.hitAreaCallback unset and // pointWithinHitArea throws on the first pointer move over it. @@ -835,7 +838,9 @@ export class ResearchWindow extends Phaser.GameObjects.Container { }) .setScrollFactor(0); cont.add(this.dUnlocks); - const btnW = 152; + // 190: the widest label is "IN PROGRESS 88%" (~166 px at 13px/ls-3) — + // 152 let it bleed past the plate edges. + const btnW = 190; const wrapW = Math.max(120, rightX + rightW - 12 - btnW - 18 - tx); this.dDesc = s .text(tx, detailY + 76, '', { @@ -864,6 +869,7 @@ export class ResearchWindow extends Phaser.GameObjects.Container { letterSpacing: 3, align: 'center', }) + .setOrigin(0.5, 0) // centre on the plate — text's default origin is (0,0) .setScrollFactor(0); const bar = s.graphics().setScrollFactor(0); // v4 Container.add(child, index) — multi-add is the ARRAY form. @@ -1264,8 +1270,13 @@ export class ResearchWindow extends Phaser.GameObjects.Container { }); } + // 'closing' counts as open: the close button flips openState in the + // SAME input pass, before the scene's pointerdown guard runs — while + // the window is still on screen (fading out) it must keep owning the + // click, or the close tap leaks through as a world click (the ship + // flies at the ✕). get isOpen() { - return this.openState === 'open' || this.openState === 'opening'; + return this.openState === 'open' || this.openState === 'opening' || this.openState === 'closing'; } /** Repaint everything from state (after research starts / completes). */