diff --git a/front/src/Phaser/Entity/Character.ts b/front/src/Phaser/Entity/Character.ts index 50681927..e2ba17ba 100644 --- a/front/src/Phaser/Entity/Character.ts +++ b/front/src/Phaser/Entity/Character.ts @@ -16,7 +16,6 @@ import type { PictureStore } from "../../Stores/PictureStore"; import { Unsubscriber, Writable, writable } from "svelte/store"; import { createColorStore } from "../../Stores/OutlineColorStore"; import type { OutlineableInterface } from '../Game/OutlineableInterface'; -import type { OutlineConfig } from '../../Utils/OutlineManager'; const playerNameY = -25; @@ -139,13 +138,6 @@ export abstract class Character extends Container implements OutlineableInterfac return { x: this.x, y: this.y }; } - public getOutlineConfig(): OutlineConfig { - return { - thickness: 2, - outlineColor: 0xffff00, - } - } - public getObjectToOutline(): Phaser.GameObjects.GameObject { return this.playerNameText; } @@ -425,11 +417,35 @@ export abstract class Character extends Container implements OutlineableInterfac return this._pictureStore; } - public setOutlineColor(color: number): void { - this.outlineColorStore.setColor(color); + public setFollowOutlineColor(color: number): void { + this.outlineColorStore.setFollowColor(color); } - public removeOutlineColor(): void { - this.outlineColorStore.removeColor(); + public removeFollowOutlineColor(): void { + this.outlineColorStore.removeFollowColor(); + } + + public setApiOutlineColor(color: number): void { + this.outlineColorStore.setApiColor(color); + } + + public removeApiOutlineColor(): void { + this.outlineColorStore.removeApiColor(); + } + + public pointerOverOutline(): void { + this.outlineColorStore.pointerOver(); + } + + public pointerOutOutline(): void { + this.outlineColorStore.pointerOut(); + } + + public characterCloseByOutline(): void { + this.outlineColorStore.characterCloseBy(); + } + + public characterFarAwayOutline(): void { + this.outlineColorStore.characterFarAway(); } } diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 3bef7101..49d1f921 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -93,10 +93,7 @@ import { GameSceneUserInputHandler } from "../UserInput/GameSceneUserInputHandle import { locale } from "../../i18n/i18n-svelte"; import type { ActivatableInterface } from './ActivatableInterface'; import { MathUtils } from '../../Utils/MathUtils'; -import { OutlineManager } from '../../Utils/OutlineManager'; -import type { OutlineableInterface } from './OutlineableInterface'; import { isOutlineable } from '../../Utils/CustomTypeGuards'; - export interface GameSceneInitInterface { initPosition: PointInterface | null; reconnecting: boolean; @@ -211,7 +208,6 @@ export class GameScene extends DirtyScene { private emoteManager!: EmoteManager; private cameraManager!: CameraManager; private pathfindingManager!: PathfindingManager; - private outlineManager!: OutlineManager; private preloading: boolean = true; private startPositionCalculator!: StartPositionCalculator; private sharedVariablesManager!: SharedVariablesManager; @@ -584,7 +580,6 @@ export class GameScene extends DirtyScene { this.gameMap.getTileDimensions() ); - this.outlineManager = new OutlineManager(this); biggestAvailableAreaStore.recompute(); this.cameraManager.startFollowPlayer(this.CurrentPlayer); @@ -670,10 +665,10 @@ export class GameScene extends DirtyScene { this.followUsersColorStoreUnsubscribe = followUsersColorStore.subscribe((color) => { if (color !== undefined) { - this.CurrentPlayer.setOutlineColor(color); + this.CurrentPlayer.setFollowOutlineColor(color); this.connection?.emitPlayerOutlineColor(color); } else { - this.CurrentPlayer.removeOutlineColor(); + this.CurrentPlayer.removeFollowOutlineColor(); this.connection?.emitPlayerOutlineColor(null); } }); @@ -1455,12 +1450,12 @@ ${escapedMessage} const green = normalizeColor(message.green); const blue = normalizeColor(message.blue); const color = (red << 16) | (green << 8) | blue; - this.CurrentPlayer.setOutlineColor(color); + this.CurrentPlayer.setApiOutlineColor(color); this.connection?.emitPlayerOutlineColor(color); }); iframeListener.registerAnswerer("removePlayerOutline", (message) => { - this.CurrentPlayer.removeOutlineColor(); + this.CurrentPlayer.removeApiOutlineColor(); this.connection?.emitPlayerOutlineColor(null); }); @@ -1703,9 +1698,13 @@ ${escapedMessage} this.selectedActivatableObjectByDistance = newNearestObject; return; } - this.outlineManager.tryRemoveOutline(this.selectedActivatableObjectByDistance); + if (isOutlineable(this.selectedActivatableObjectByDistance)) { + this.selectedActivatableObjectByDistance?.characterFarAwayOutline(); + } this.selectedActivatableObjectByDistance = newNearestObject; - this.outlineManager.tryAddOutline(this.selectedActivatableObjectByDistance); + if (isOutlineable(this.selectedActivatableObjectByDistance)) { + this.selectedActivatableObjectByDistance?.characterCloseByOutline(); + } } private updateDistanceForSingleActivatableObject(object: ActivatableInterface): void { @@ -1996,7 +1995,7 @@ ${escapedMessage} addPlayerData.companion !== null ? lazyLoadCompanionResource(this.load, addPlayerData.companion) : undefined ); if (addPlayerData.outlineColor !== undefined) { - player.setOutlineColor(addPlayerData.outlineColor); + player.setApiOutlineColor(addPlayerData.outlineColor); } this.MapPlayers.add(player); this.MapPlayersByKey.set(player.userId, player); @@ -2006,18 +2005,26 @@ ${escapedMessage} if (this.selectedActivatableObjectByPointer === player) { return; } - this.outlineManager.tryRemoveOutline(this.selectedActivatableObjectByDistance); - this.outlineManager.tryRemoveOutline(this.selectedActivatableObjectByPointer); + if (isOutlineable(this.selectedActivatableObjectByDistance)) { + this.selectedActivatableObjectByDistance?.characterFarAwayOutline(); + } + if (isOutlineable(this.selectedActivatableObjectByPointer)) { + this.selectedActivatableObjectByPointer?.pointerOutOutline(); + } this.selectedActivatableObjectByPointer = player; - this.outlineManager.tryAddOutline(player); + if (isOutlineable(this.selectedActivatableObjectByPointer)) { + this.selectedActivatableObjectByPointer?.pointerOverOutline(); + } this.markDirty(); }); player.on(Phaser.Input.Events.POINTER_OUT, () => { - this.outlineManager.tryRemoveOutline(this.selectedActivatableObjectByPointer); + if (isOutlineable(this.selectedActivatableObjectByPointer)) { + this.selectedActivatableObjectByPointer?.pointerOutOutline(); + } this.selectedActivatableObjectByPointer = undefined; - if (this.selectedActivatableObjectByDistance) { - this.outlineManager.tryAddOutline(this.selectedActivatableObjectByDistance); + if (isOutlineable(this.selectedActivatableObjectByDistance)) { + this.selectedActivatableObjectByDistance?.characterCloseByOutline(); } this.markDirty(); }); @@ -2132,9 +2139,9 @@ ${escapedMessage} return; } if (message.removeOutlineColor) { - character.removeOutlineColor(); + character.removeApiOutlineColor(); } else { - character.setOutlineColor(message.outlineColor); + character.setApiOutlineColor(message.outlineColor); } } @@ -2289,6 +2296,6 @@ ${escapedMessage} } public getSelectedActivatableObject(): ActivatableInterface | undefined { - return this.selectedActivatableObjectByDistance; + return this.selectedActivatableObjectByPointer ?? this.selectedActivatableObjectByDistance; } } diff --git a/front/src/Phaser/Game/OutlineableInterface.ts b/front/src/Phaser/Game/OutlineableInterface.ts index b135e17a..f2657d61 100644 --- a/front/src/Phaser/Game/OutlineableInterface.ts +++ b/front/src/Phaser/Game/OutlineableInterface.ts @@ -1,6 +1,11 @@ -import type { OutlineConfig } from '../../Utils/OutlineManager'; export interface OutlineableInterface { - getObjectToOutline: () => Phaser.GameObjects.GameObject; - getOutlineConfig: () => OutlineConfig; + setFollowOutlineColor(color: number): void + removeFollowOutlineColor(): void + setApiOutlineColor(color: number): void + removeApiOutlineColor(): void + pointerOverOutline(): void + pointerOutOutline(): void + characterCloseByOutline(): void + characterFarAwayOutline(): void } \ No newline at end of file diff --git a/front/src/Stores/OutlineColorStore.ts b/front/src/Stores/OutlineColorStore.ts index 1618eebc..1bb6fd66 100644 --- a/front/src/Stores/OutlineColorStore.ts +++ b/front/src/Stores/OutlineColorStore.ts @@ -3,14 +3,17 @@ import { writable } from "svelte/store"; export function createColorStore() { const { subscribe, set } = writable(undefined); - let color: number | undefined = undefined; - let focused: boolean = false; + let followColor: number | undefined = undefined; + let apiColor: number | undefined = undefined; + + let pointedByPointer: boolean = false; + let pointedByCharacter: boolean = false; const updateColor = () => { - if (focused) { + if (pointedByPointer || pointedByCharacter) { set(0xffff00); } else { - set(color); + set(followColor ?? apiColor); } }; @@ -18,22 +21,42 @@ export function createColorStore() { subscribe, pointerOver() { - focused = true; + pointedByPointer = true; updateColor(); }, pointerOut() { - focused = false; + pointedByPointer = false; updateColor(); }, - setColor(newColor: number) { - color = newColor; + characterCloseBy() { + pointedByCharacter = true; updateColor(); }, - removeColor() { - color = undefined; + characterFarAway() { + pointedByCharacter = false; + updateColor(); + }, + + setFollowColor(newColor: number) { + followColor = newColor; + updateColor(); + }, + + removeFollowColor() { + followColor = undefined; + updateColor(); + }, + + setApiColor(newColor: number) { + apiColor = newColor; + updateColor(); + }, + + removeApiColor() { + apiColor = undefined; updateColor(); }, }; diff --git a/front/src/Utils/OutlineManager.ts b/front/src/Utils/OutlineManager.ts deleted file mode 100644 index c476af96..00000000 --- a/front/src/Utils/OutlineManager.ts +++ /dev/null @@ -1,44 +0,0 @@ -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 { - thickness: number; - outlineColor: number; -} - -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) || this.objectsWithOutline.includes(object)) { - return; - } - this.outlinePlugin?.add(object.getObjectToOutline(), object.getOutlineConfig()); - this.objectsWithOutline.push(object); - } - - public tryRemoveOutline(object: unknown): void { - 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