diff --git a/front/src/Phaser/Entity/Character.ts b/front/src/Phaser/Entity/Character.ts index db3f2f8d..50681927 100644 --- a/front/src/Phaser/Entity/Character.ts +++ b/front/src/Phaser/Entity/Character.ts @@ -105,13 +105,6 @@ export abstract class Character extends Container implements OutlineableInterfac hitAreaCallback: Phaser.Geom.Circle.Contains, //eslint-disable-line @typescript-eslint/unbound-method useHandCursor: true, }); - - this.on("pointerover", () => { - this.outlineColorStore.pointerOver(); - }); - this.on("pointerout", () => { - this.outlineColorStore.pointerOut(); - }); } this.outlineColorStoreUnsubscribe = this.outlineColorStore.subscribe((color) => { diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 5ba8a0ed..3bef7101 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -194,7 +194,8 @@ export class GameScene extends DirtyScene { private gameMap!: GameMap; private actionableItems: Map = new Map(); // The item that can be selected by pressing the space key. - private selectedActivatableObject?: ActivatableInterface; + private selectedActivatableObjectByDistance?: ActivatableInterface; + private selectedActivatableObjectByPointer?: ActivatableInterface; private activatableObjectsDistances: Map = new Map(); private outlinedItem: ActionableItem | null = null; public userInputManager!: UserInputManager; @@ -1688,18 +1689,23 @@ ${escapedMessage} this.pushPlayerPosition(event); this.gameMap.setPosition(event.x, event.y); this.updateActivatableObjectsDistances(); - this.deduceSelectedActivatableObject(); + this.deduceSelectedActivatableObjectByDistance(); // this.outlineItem(event); } - private deduceSelectedActivatableObject(): void { + private deduceSelectedActivatableObjectByDistance(): void { const newNearestObject = this.findNearestActivatableObject(); - if (this.selectedActivatableObject === newNearestObject) { + if (this.selectedActivatableObjectByDistance === newNearestObject) { return; } - this.outlineManager.tryRemoveOutline(this.selectedActivatableObject); - this.selectedActivatableObject = newNearestObject; - this.outlineManager.tryAddOutline(this.selectedActivatableObject); + // update value but do not change the outline + if (this.selectedActivatableObjectByPointer) { + this.selectedActivatableObjectByDistance = newNearestObject; + return; + } + this.outlineManager.tryRemoveOutline(this.selectedActivatableObjectByDistance); + this.selectedActivatableObjectByDistance = newNearestObject; + this.outlineManager.tryAddOutline(this.selectedActivatableObjectByDistance); } private updateDistanceForSingleActivatableObject(object: ActivatableInterface): void { @@ -1764,7 +1770,7 @@ ${escapedMessage} this.companion, this.companion !== null ? lazyLoadCompanionResource(this.load, this.companion) : undefined ); - this.CurrentPlayer.on("pointerdown", (pointer: Phaser.Input.Pointer) => { + this.CurrentPlayer.on(Phaser.Input.Events.POINTER_DOWN, (pointer: Phaser.Input.Pointer) => { if (pointer.wasTouch && (pointer.event as TouchEvent).touches.length > 1) { return; //we don't want the menu to open when pinching on a touch screen. } @@ -1901,7 +1907,7 @@ ${escapedMessage} const remotePlayer = this.MapPlayersByKey.get(event.event.userId); if (remotePlayer) { this.updateDistanceForSingleActivatableObject(remotePlayer); - this.deduceSelectedActivatableObject(); + this.deduceSelectedActivatableObjectByDistance(); } break; case "GroupCreatedUpdatedEvent": @@ -1995,6 +2001,26 @@ ${escapedMessage} this.MapPlayers.add(player); this.MapPlayersByKey.set(player.userId, player); player.updatePosition(addPlayerData.position); + + player.on(Phaser.Input.Events.POINTER_OVER, () => { + if (this.selectedActivatableObjectByPointer === player) { + return; + } + this.outlineManager.tryRemoveOutline(this.selectedActivatableObjectByDistance); + this.outlineManager.tryRemoveOutline(this.selectedActivatableObjectByPointer); + this.selectedActivatableObjectByPointer = player; + this.outlineManager.tryAddOutline(player); + this.markDirty(); + }); + + player.on(Phaser.Input.Events.POINTER_OUT, () => { + this.outlineManager.tryRemoveOutline(this.selectedActivatableObjectByPointer); + this.selectedActivatableObjectByPointer = undefined; + if (this.selectedActivatableObjectByDistance) { + this.outlineManager.tryAddOutline(this.selectedActivatableObjectByDistance); + } + this.markDirty(); + }); } /** @@ -2263,6 +2289,6 @@ ${escapedMessage} } public getSelectedActivatableObject(): ActivatableInterface | undefined { - return this.selectedActivatableObject; + return this.selectedActivatableObjectByDistance; } } diff --git a/front/src/Utils/OutlineManager.ts b/front/src/Utils/OutlineManager.ts index 05aa82a0..c476af96 100644 --- a/front/src/Utils/OutlineManager.ts +++ b/front/src/Utils/OutlineManager.ts @@ -1,4 +1,5 @@ import type OutlinePipelinePlugin from 'phaser3-rex-plugins/plugins/outlinepipeline-plugin.js'; +import type { OutlineableInterface } from '../Phaser/Game/OutlineableInterface'; import { isOutlineable } from './CustomTypeGuards'; export interface OutlineConfig { @@ -10,25 +11,34 @@ export class OutlineManager { private scene: Phaser.Scene; + private objectsWithOutline: OutlineableInterface[]; + private outlinePlugin?: OutlinePipelinePlugin constructor(scene: Phaser.Scene) { this.scene = scene; + this.objectsWithOutline = []; this.outlinePlugin = this.scene.plugins.get("rexOutlinePipeline") as unknown as OutlinePipelinePlugin | undefined; } public tryAddOutline(object: unknown): void { - if (!isOutlineable(object)) { + if (!isOutlineable(object) || this.objectsWithOutline.includes(object)) { return; } this.outlinePlugin?.add(object.getObjectToOutline(), object.getOutlineConfig()); + this.objectsWithOutline.push(object); } public tryRemoveOutline(object: unknown): void { - if (!isOutlineable(object)) { + if (!isOutlineable(object) || !this.objectsWithOutline.includes(object)) { return; } this.outlinePlugin?.remove(object.getObjectToOutline()); + const index = this.objectsWithOutline.findIndex(obj => obj === object); + if (index === -1) { + return; + } + this.objectsWithOutline.splice(index, 1); } } \ No newline at end of file