From 433d4b4fc93a27579a36ab2cf6e8a20d20385d3e Mon Sep 17 00:00:00 2001 From: Moka <54149968+MokaStitcher@users.noreply.github.com> Date: Tue, 5 Nov 2024 02:24:17 +0100 Subject: [PATCH] [P3][UI][QoL] Fix tooltips going out of screen on mobile & other improvements (#4792) * [ui] Fix tooltip placement when using touchscreen * [ui] make candy friendship tooltip hitbox bigger --- src/ui/starter-select-ui-handler.ts | 79 ++++++++++++++--------------- src/ui/summary-ui-handler.ts | 4 +- src/ui/ui.ts | 35 ++++++++++--- 3 files changed, 68 insertions(+), 50 deletions(-) diff --git a/src/ui/starter-select-ui-handler.ts b/src/ui/starter-select-ui-handler.ts index 3a29f9431e7..bb4dc74d44e 100644 --- a/src/ui/starter-select-ui-handler.ts +++ b/src/ui/starter-select-ui-handler.ts @@ -242,6 +242,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { private pokemonEggMoveContainers: Phaser.GameObjects.Container[]; private pokemonEggMoveBgs: Phaser.GameObjects.NineSlice[]; private pokemonEggMoveLabels: Phaser.GameObjects.Text[]; + private pokemonCandyContainer: Phaser.GameObjects.Container; private pokemonCandyIcon: Phaser.GameObjects.Sprite; private pokemonCandyDarknessOverlay: Phaser.GameObjects.Sprite; private pokemonCandyOverlayIcon: Phaser.GameObjects.Sprite; @@ -686,31 +687,36 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.pokemonLuckText.setOrigin(0, 0); this.starterSelectContainer.add(this.pokemonLuckText); - this.pokemonCandyIcon = this.scene.add.sprite(4.5, 18, "candy"); + // Candy icon and count + this.pokemonCandyContainer = this.scene.add.container(4.5, 18); + + this.pokemonCandyIcon = this.scene.add.sprite(0, 0, "candy"); this.pokemonCandyIcon.setScale(0.5); this.pokemonCandyIcon.setOrigin(0, 0); - this.starterSelectContainer.add(this.pokemonCandyIcon); + this.pokemonCandyContainer.add(this.pokemonCandyIcon); - this.pokemonFormText = addTextObject(this.scene, 6, 42, "Form", TextStyle.WINDOW_ALT, { fontSize: "42px" }); - this.pokemonFormText.setOrigin(0, 0); - this.starterSelectContainer.add(this.pokemonFormText); - - this.pokemonCandyOverlayIcon = this.scene.add.sprite(4.5, 18, "candy_overlay"); + this.pokemonCandyOverlayIcon = this.scene.add.sprite(0, 0, "candy_overlay"); this.pokemonCandyOverlayIcon.setScale(0.5); this.pokemonCandyOverlayIcon.setOrigin(0, 0); - this.starterSelectContainer.add(this.pokemonCandyOverlayIcon); + this.pokemonCandyContainer.add(this.pokemonCandyOverlayIcon); - this.pokemonCandyDarknessOverlay = this.scene.add.sprite(4.5, 18, "candy"); + this.pokemonCandyDarknessOverlay = this.scene.add.sprite(0, 0, "candy"); this.pokemonCandyDarknessOverlay.setScale(0.5); this.pokemonCandyDarknessOverlay.setOrigin(0, 0); this.pokemonCandyDarknessOverlay.setTint(0x000000); this.pokemonCandyDarknessOverlay.setAlpha(0.50); - this.pokemonCandyDarknessOverlay.setInteractive(new Phaser.Geom.Rectangle(0, 0, 16, 16), Phaser.Geom.Rectangle.Contains); - this.starterSelectContainer.add(this.pokemonCandyDarknessOverlay); + this.pokemonCandyContainer.add(this.pokemonCandyDarknessOverlay); - this.pokemonCandyCountText = addTextObject(this.scene, 14, 18, "x0", TextStyle.WINDOW_ALT, { fontSize: "56px" }); + this.pokemonCandyCountText = addTextObject(this.scene, 9.5, 0, "x0", TextStyle.WINDOW_ALT, { fontSize: "56px" }); this.pokemonCandyCountText.setOrigin(0, 0); - this.starterSelectContainer.add(this.pokemonCandyCountText); + this.pokemonCandyContainer.add(this.pokemonCandyCountText); + + this.pokemonCandyContainer.setInteractive(new Phaser.Geom.Rectangle(0, 0, 30, 20), Phaser.Geom.Rectangle.Contains); + this.starterSelectContainer.add(this.pokemonCandyContainer); + + this.pokemonFormText = addTextObject(this.scene, 6, 42, "Form", TextStyle.WINDOW_ALT, { fontSize: "42px" }); + this.pokemonFormText.setOrigin(0, 0); + this.starterSelectContainer.add(this.pokemonFormText); this.pokemonCaughtHatchedContainer = this.scene.add.container(2, 25); this.pokemonCaughtHatchedContainer.setScale(0.5); @@ -2822,10 +2828,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.pokemonShinyIcon.setY(135); this.pokemonShinyIcon.setFrame(getVariantIcon(variant)); [ - this.pokemonCandyIcon, - this.pokemonCandyOverlayIcon, - this.pokemonCandyDarknessOverlay, - this.pokemonCandyCountText, + this.pokemonCandyContainer, this.pokemonHatchedIcon, this.pokemonHatchedCountText ].map(c => c.setVisible(false)); @@ -2834,31 +2837,26 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.pokemonCaughtHatchedContainer.setY(25); this.pokemonShinyIcon.setY(117); this.pokemonCandyIcon.setTint(argbFromRgba(rgbHexToRgba(colorScheme[0]))); - this.pokemonCandyIcon.setVisible(true); this.pokemonCandyOverlayIcon.setTint(argbFromRgba(rgbHexToRgba(colorScheme[1]))); - this.pokemonCandyOverlayIcon.setVisible(true); - this.pokemonCandyDarknessOverlay.setVisible(true); this.pokemonCandyCountText.setText(`x${this.scene.gameData.starterData[species.speciesId].candyCount}`); - this.pokemonCandyCountText.setVisible(true); + this.pokemonCandyContainer.setVisible(true); this.pokemonFormText.setY(42); this.pokemonHatchedIcon.setVisible(true); this.pokemonHatchedCountText.setVisible(true); const { currentFriendship, friendshipCap } = this.getFriendship(this.lastSpecies.speciesId); const candyCropY = 16 - (16 * (currentFriendship / friendshipCap)); - - if (this.pokemonCandyDarknessOverlay.visible) { - this.pokemonCandyDarknessOverlay.on("pointerover", () => { - this.scene.ui.showTooltip("", `${currentFriendship}/${friendshipCap}`, true); - this.activeTooltip = "CANDY"; - }); - this.pokemonCandyDarknessOverlay.on("pointerout", () => { - this.scene.ui.hideTooltip(); - this.activeTooltip = undefined; - }); - } - this.pokemonCandyDarknessOverlay.setCrop(0, 0, 16, candyCropY); + + this.pokemonCandyContainer.on("pointerover", () => { + this.scene.ui.showTooltip("", `${currentFriendship}/${friendshipCap}`, true); + this.activeTooltip = "CANDY"; + }); + this.pokemonCandyContainer.on("pointerout", () => { + this.scene.ui.hideTooltip(); + this.activeTooltip = undefined; + }); + } @@ -2934,10 +2932,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.pokemonPassiveLabelText.setVisible(false); this.pokemonNatureLabelText.setVisible(false); this.pokemonCaughtHatchedContainer.setVisible(false); - this.pokemonCandyIcon.setVisible(false); - this.pokemonCandyOverlayIcon.setVisible(false); - this.pokemonCandyDarknessOverlay.setVisible(false); - this.pokemonCandyCountText.setVisible(false); + this.pokemonCandyContainer.setVisible(false); this.pokemonFormText.setVisible(false); const defaultDexAttr = this.scene.gameData.getSpeciesDefaultDexAttr(species, true, true); @@ -2971,10 +2966,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.pokemonPassiveLabelText.setVisible(false); this.pokemonNatureLabelText.setVisible(false); this.pokemonCaughtHatchedContainer.setVisible(false); - this.pokemonCandyIcon.setVisible(false); - this.pokemonCandyOverlayIcon.setVisible(false); - this.pokemonCandyDarknessOverlay.setVisible(false); - this.pokemonCandyCountText.setVisible(false); + this.pokemonCandyContainer.setVisible(false); this.pokemonFormText.setVisible(false); this.setSpeciesDetails(species!, { // TODO: is this bang correct? @@ -3005,7 +2997,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { || !isNullOrUndefined(formIndex) || !isNullOrUndefined(shiny) || !isNullOrUndefined(variant); if (this.activeTooltip === "CANDY") { - if (this.lastSpecies) { + if (this.lastSpecies && this.pokemonCandyContainer.visible) { const { currentFriendship, friendshipCap } = this.getFriendship(this.lastSpecies.speciesId); this.scene.ui.editTooltip("", `${currentFriendship}/${friendshipCap}`); } else { @@ -3230,6 +3222,9 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.pokemonPassiveLockedIcon.setVisible(!isUnlocked); this.pokemonPassiveLockedIcon.setPosition(iconPosition.x, iconPosition.y); + } else if (this.activeTooltip === "PASSIVE") { + // No passive and passive tooltip is active > hide it + this.scene.ui.hideTooltip(); } this.pokemonNatureText.setText(getNatureName(natureIndex as unknown as Nature, true, true, false, this.scene.uiTheme)); diff --git a/src/ui/summary-ui-handler.ts b/src/ui/summary-ui-handler.ts index 9a61dd0f688..4b36867571e 100644 --- a/src/ui/summary-ui-handler.ts +++ b/src/ui/summary-ui-handler.ts @@ -184,7 +184,7 @@ export default class SummaryUiHandler extends UiHandler { this.candyShadow.setTint(0x000000); this.candyShadow.setAlpha(0.50); this.candyShadow.setScale(0.8); - this.candyShadow.setInteractive(new Phaser.Geom.Rectangle(0, 0, 16, 16), Phaser.Geom.Rectangle.Contains); + this.candyShadow.setInteractive(new Phaser.Geom.Rectangle(0, 0, 30, 16), Phaser.Geom.Rectangle.Contains); this.summaryContainer.add(this.candyShadow); this.candyCountText = addTextObject(this.scene, 20, -146, "x0", TextStyle.WINDOW_ALT, { fontSize: "76px" }); @@ -203,7 +203,7 @@ export default class SummaryUiHandler extends UiHandler { this.friendshipShadow.setTint(0x000000); this.friendshipShadow.setAlpha(0.50); this.friendshipShadow.setScale(0.8); - this.friendshipShadow.setInteractive(new Phaser.Geom.Rectangle(0, 0, 16, 16), Phaser.Geom.Rectangle.Contains); + this.friendshipShadow.setInteractive(new Phaser.Geom.Rectangle(0, 0, 50, 16), Phaser.Geom.Rectangle.Contains); this.summaryContainer.add(this.friendshipShadow); this.friendshipText = addTextObject(this.scene, 20, -66, "x0", TextStyle.WINDOW_ALT, { fontSize: "76px" }); diff --git a/src/ui/ui.ts b/src/ui/ui.ts index 63cd48ab1cd..fc8fa94c848 100644 --- a/src/ui/ui.ts +++ b/src/ui/ui.ts @@ -391,6 +391,7 @@ export default class UI extends Phaser.GameObjects.Container { this.tooltipContent.y = title ? 16 : 4; this.tooltipBg.width = Math.min(Math.max(this.tooltipTitle.displayWidth, this.tooltipContent.displayWidth) + 12, 838); this.tooltipBg.height = (title ? 31 : 19) + 10.5 * (wrappedContent.split("\n").length - 1); + this.tooltipTitle.x = this.tooltipBg.width / 2; } hideTooltip(): void { @@ -400,12 +401,34 @@ export default class UI extends Phaser.GameObjects.Container { update(): void { if (this.tooltipContainer.visible) { - const xReverse = this.scene.game.input.mousePointer && this.scene.game.input.mousePointer.x >= this.scene.game.canvas.width - this.tooltipBg.width * 6 - 12; - const yReverse = this.scene.game.input.mousePointer && this.scene.game.input.mousePointer.y >= this.scene.game.canvas.height - this.tooltipBg.height * 6 - 12; - this.tooltipContainer.setPosition( - !xReverse ? this.scene.game.input.mousePointer!.x / 6 + 2 : this.scene.game.input.mousePointer!.x / 6 - this.tooltipBg.width - 2, - !yReverse ? this.scene.game.input.mousePointer!.y / 6 + 2 : this.scene.game.input.mousePointer!.y / 6 - this.tooltipBg.height - 2, - ); + const isTouch = (this.scene as BattleScene).inputMethod === "touch"; + const pointerX = this.scene.game.input.activePointer.x; + const pointerY = this.scene.game.input.activePointer.y; + const tooltipWidth = this.tooltipBg.width; + const tooltipHeight = this.tooltipBg.height; + const padding = 2; + + // Default placement is top left corner of the screen on mobile. Otherwise below the cursor, to the right + let x = isTouch ? padding : pointerX / 6 + padding; + let y = isTouch ? padding : pointerY / 6 + padding; + + if (isTouch) { + // If we are in the top left quadrant on mobile, move the tooltip to the top right corner + if (pointerX <= this.scene.game.canvas.width / 2 && pointerY <= this.scene.game.canvas.height / 2) { + x = this.scene.game.canvas.width / 6 - tooltipWidth - padding; + } + } else { + // If the tooltip would go offscreen on the right, or is close to it, move to the left of the cursor + if (x + tooltipWidth + padding > this.scene.game.canvas.width / 6) { + x = Math.max(padding, pointerX / 6 - tooltipWidth - padding); + } + // If the tooltip would go offscreen at the bottom, or is close to it, move above the cursor + if (y + tooltipHeight + padding > this.scene.game.canvas.height / 6) { + y = Math.max(padding, pointerY / 6 - tooltipHeight - padding); + } + } + + this.tooltipContainer.setPosition(x, y); } }