diff --git a/front/src/Components/App.svelte b/front/src/Components/App.svelte index 8b033e5f..06996ff9 100644 --- a/front/src/Components/App.svelte +++ b/front/src/Components/App.svelte @@ -26,6 +26,7 @@ import {soundPlayingStore} from "../Stores/SoundPlayingStore"; import ErrorDialog from "./UI/ErrorDialog.svelte"; import Menu from "./Menu/Menu.svelte"; + import EmoteMenu from "./EmoteMenu/EmoteMenu.svelte"; import VideoOverlay from "./Video/VideoOverlay.svelte"; import {gameOverlayVisibilityStore} from "../Stores/GameOverlayStoreVisibility"; import AdminMessage from "./TypeMessage/BanMessage.svelte"; @@ -111,6 +112,11 @@ {/if} + {#if $gameOverlayVisibilityStore} +
+ +
+ {/if} {#if $gameOverlayVisibilityStore}
diff --git a/front/src/Components/EmoteMenu/EmoteMenu.svelte b/front/src/Components/EmoteMenu/EmoteMenu.svelte new file mode 100644 index 00000000..1a1de281 --- /dev/null +++ b/front/src/Components/EmoteMenu/EmoteMenu.svelte @@ -0,0 +1,65 @@ + + +
+
+
+ + \ No newline at end of file diff --git a/front/src/Phaser/Components/EmoteMenu.ts b/front/src/Phaser/Components/EmoteMenu.ts deleted file mode 100644 index 744c8b12..00000000 --- a/front/src/Phaser/Components/EmoteMenu.ts +++ /dev/null @@ -1,62 +0,0 @@ -import DOMElement = Phaser.GameObjects.DOMElement; -import { DEPTH_UI_INDEX } from "../Game/DepthIndexes"; -import { waScaleManager } from "../Services/WaScaleManager"; -import type { UserInputManager } from "../UserInput/UserInputManager"; -import { EmojiButton } from "@joeattardi/emoji-button"; -import { HtmlUtils } from "../../WebRtc/HtmlUtils"; - -export const EmoteMenuClickEvent = "emoteClick"; - -export class EmoteMenu extends Phaser.GameObjects.Container { - private resizeCallback: OmitThisParameter<() => void>; - private container: DOMElement; - private picker: EmojiButton; - - constructor(scene: Phaser.Scene, x: number, y: number, private userInputManager: UserInputManager) { - super(scene, x, y); - this.setDepth(DEPTH_UI_INDEX); - this.scene.add.existing(this); - this.container = new DOMElement(this.scene, 0, 0, "div", "", ""); - this.container.setClassName("emoji-container"); - const scalingFactor = waScaleManager.uiScalingFactor * 0.5; - this.container.setScale(scalingFactor); - this.add(this.container); - const emojiContainer = HtmlUtils.querySelectorOrFail(".emoji-container"); - this.picker = new EmojiButton({ rootElement: emojiContainer }); - - this.picker.on("emoji", (selection) => { - this.emit(EmoteMenuClickEvent, selection.emoji); - }); - - this.picker.on("hidden", () => { - this.userInputManager.restoreControls(); - }); - - this.resize(); - this.resizeCallback = this.resize.bind(this); - this.scene.scale.on(Phaser.Scale.Events.RESIZE, this.resizeCallback); - } - - public isOpen(): boolean { - return this.picker.isPickerVisible(); - } - - public openPicker() { - this.userInputManager.disableControls(); - const emojiContainer = HtmlUtils.querySelectorOrFail(".emoji-container"); - this.picker.showPicker(emojiContainer); - } - - public closePicker() { - this.picker.hidePicker(); - } - - private resize() { - this.setScale(waScaleManager.uiScalingFactor); - } - - public destroy() { - this.scene.scale.removeListener(Phaser.Scale.Events.RESIZE, this.resizeCallback); - super.destroy(); - } -} diff --git a/front/src/Phaser/Entity/Character.ts b/front/src/Phaser/Entity/Character.ts index 890ebbac..c2e89cb2 100644 --- a/front/src/Phaser/Entity/Character.ts +++ b/front/src/Phaser/Entity/Character.ts @@ -282,50 +282,55 @@ export abstract class Character extends Container { super.destroy(); } - playEmote(emote: string) { - this.cancelPreviousEmote(); - - const scalingFactor = waScaleManager.uiScalingFactor; - const emoteY = -60; - - this.playerName.setVisible(false); - this.emote = new Text(this.scene, -12, 0, emote, { fontFamily: '"Twemoji Mozilla"', fontSize: "24px" }); - this.emote.setAlpha(0); - this.add(this.emote); - this.createStartTransition(scalingFactor, emoteY); + isSilent() { + isSilentStore.set(true); + } + noSilent() { + isSilentStore.set(false); } - private createStartTransition(scalingFactor: number, emoteY: number) { + playEmote(emote: string) { + this.cancelPreviousEmote(); + const emoteY = -45; + this.playerName.setVisible(false); + this.emote = new Text(this.scene, -10, 0, emote, { fontFamily: '"twemoji"', fontSize: "20px" }); + this.emote.setAlpha(0); + this.add(this.emote); + this.createStartTransition(emoteY); + } + + private createStartTransition(emoteY: number) { this.emoteTween = this.scene?.tweens.add({ targets: this.emote, props: { - scale: scalingFactor, alpha: 1, y: emoteY, }, ease: "Power2", duration: 500, onComplete: () => { - this.startPulseTransition(emoteY, scalingFactor); + this.startPulseTransition(emoteY); }, }); } - private startPulseTransition(emoteY: number, scalingFactor: number) { - this.emoteTween = this.scene?.tweens.add({ - targets: this.emote, - props: { - y: emoteY * 1.3, - scale: scalingFactor * 1.1, - }, - duration: 250, - yoyo: true, - repeat: 1, - completeDelay: 200, - onComplete: () => { - this.startExitTransition(emoteY); - }, - }); + private startPulseTransition(emoteY: number) { + if (this.emote) { + this.emoteTween = this.scene?.tweens.add({ + targets: this.emote, + props: { + y: emoteY * 1.3, + scale: this.emote.scale * 1.1, + }, + duration: 250, + yoyo: true, + repeat: 1, + completeDelay: 200, + onComplete: () => { + this.startExitTransition(emoteY); + }, + }); + } } private startExitTransition(emoteY: number) { diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index fd466952..6a40423f 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -82,6 +82,7 @@ import { biggestAvailableAreaStore } from "../../Stores/BiggestAvailableAreaStor import { SharedVariablesManager } from "./SharedVariablesManager"; import { playersStore } from "../../Stores/PlayersStore"; import { chatVisibilityStore } from "../../Stores/ChatStore"; +import { emoteStore } from "../../Stores/EmoteStore"; import { audioManagerFileStore, audioManagerVisibilityStore, @@ -93,7 +94,7 @@ import { userIsAdminStore } from "../../Stores/GameStore"; import { layoutManagerActionStore } from "../../Stores/LayoutManagerStore"; import { EmbeddedWebsiteManager } from "./EmbeddedWebsiteManager"; import { GameMapPropertiesListener } from "./GameMapPropertiesListener"; -import type { RadialMenuItem } from "../Components/RadialMenu"; +import { get } from "svelte/store"; export interface GameSceneInitInterface { initPosition: PointInterface | null; @@ -171,6 +172,7 @@ export class GameScene extends DirtyScene { private iframeSubscriptionList!: Array; private peerStoreUnsubscribe!: () => void; private chatVisibilityUnsubscribe!: () => void; + private emoteUnsubscribe!: () => void; private biggestAvailableAreaStoreUnsubscribe!: () => void; MapUrlFile: string; roomUrl: string; @@ -614,6 +616,15 @@ export class GameScene extends DirtyScene { this.openChatIcon.setVisible(!v); }); + this.emoteUnsubscribe = emoteStore.subscribe(() => { + const emoteKey = get(emoteStore); + if (emoteKey) { + this.CurrentPlayer?.playEmote(emoteKey); + this.connection?.emitEmoteEvent(emoteKey); + emoteStore.set(null); + } + }); + Promise.all([this.connectionAnswerPromise as Promise, ...scriptPromises]).then(() => { this.scene.wake(); }); @@ -1302,6 +1313,7 @@ ${escapedMessage} this.emoteManager.destroy(); this.peerStoreUnsubscribe(); this.chatVisibilityUnsubscribe(); + this.emoteUnsubscribe(); this.biggestAvailableAreaStoreUnsubscribe(); iframeListener.unregisterAnswerer("getState"); iframeListener.unregisterAnswerer("loadTileset"); diff --git a/front/src/Phaser/Player/Player.ts b/front/src/Phaser/Player/Player.ts index ab8f7575..bd6c261a 100644 --- a/front/src/Phaser/Player/Player.ts +++ b/front/src/Phaser/Player/Player.ts @@ -3,7 +3,8 @@ import type { GameScene } from "../Game/GameScene"; import { UserInputEvent, UserInputManager } from "../UserInput/UserInputManager"; import { Character } from "../Entity/Character"; import { userMovingStore } from "../../Stores/GameStore"; -import { EmoteMenu, EmoteMenuClickEvent } from "../Components/EmoteMenu"; +import { get } from "svelte/store"; +import { emoteMenuStore } from "../../Stores/EmoteStore"; export const hasMovedEventName = "hasMoved"; export const requestEmoteEventName = "requestEmote"; @@ -11,8 +12,6 @@ export const requestEmoteEventName = "requestEmote"; export class Player extends Character { private previousDirection: string = PlayerAnimationDirections.Down; private wasMoving: boolean = false; - private emoteMenu: EmoteMenu | null = null; - private updateListener: () => void; constructor( Scene: GameScene, @@ -30,14 +29,6 @@ export class Player extends Character { //the current player model should be push away by other players to prevent conflict this.getBody().setImmovable(false); - - this.updateListener = () => { - if (this.emoteMenu) { - this.emoteMenu.x = this.x; - this.emoteMenu.y = this.y; - } - }; - this.scene.events.addListener("postupdate", this.updateListener); } moveUser(delta: number): void { @@ -94,43 +85,16 @@ export class Player extends Character { return this.wasMoving; } + playEmote(emote: string) { + super.playEmote(emote); + emoteMenuStore.set(false); + } + openOrCloseEmoteMenu() { - if (!this.emoteMenu) { - this.emoteMenu = new EmoteMenu(this.scene, this.x, this.y, this.userInputManager); - } - - if (this.emoteMenu.isOpen()) { - this.closeEmoteMenu(); + if (get(emoteMenuStore)) { + emoteMenuStore.set(false); } else { - this.openEmoteMenu(); + emoteMenuStore.set(true); } } - - openEmoteMenu(): void { - this.cancelPreviousEmote(); - if (!this.emoteMenu) return; - this.emoteMenu.openPicker(); - this.emoteMenu.on(EmoteMenuClickEvent, (emote: string) => { - this.closeEmoteMenu(); - this.emit(requestEmoteEventName, emote); - this.playEmote(emote); - }); - } - - isSilent() { - super.isSilent(); - } - noSilent() { - super.noSilent(); - } - - closeEmoteMenu(): void { - if (!this.emoteMenu) return; - this.emoteMenu.closePicker(); - } - - destroy() { - this.scene.events.removeListener("postupdate", this.updateListener); - super.destroy(); - } } diff --git a/front/src/Stores/EmoteStore.ts b/front/src/Stores/EmoteStore.ts new file mode 100644 index 00000000..ddff3654 --- /dev/null +++ b/front/src/Stores/EmoteStore.ts @@ -0,0 +1,4 @@ +import { writable } from "svelte/store"; + +export const emoteStore = writable(null); +export const emoteMenuStore = writable(false);