Merge pull request #1437 from Lurkars/twemojiEmoteMenuSvelte
Twemoji emote menu svelte (upgrade of #1301)
This commit is contained in:
commit
9b13a6780c
19 changed files with 355 additions and 169 deletions
|
@ -1,13 +1,12 @@
|
|||
import {POSTHOG_API_KEY, POSTHOG_URL} from "../Enum/EnvironmentVariable";
|
||||
import { POSTHOG_API_KEY, POSTHOG_URL } from "../Enum/EnvironmentVariable";
|
||||
|
||||
class AnalyticsClient {
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
private posthogPromise: Promise<any>;
|
||||
|
||||
constructor() {
|
||||
if (POSTHOG_API_KEY && POSTHOG_URL) {
|
||||
this.posthogPromise = import('posthog-js').then(({default: posthog}) => {
|
||||
this.posthogPromise = import("posthog-js").then(({ default: posthog }) => {
|
||||
posthog.init(POSTHOG_API_KEY, { api_host: POSTHOG_URL, disable_cookie: true });
|
||||
return posthog;
|
||||
});
|
||||
|
@ -17,45 +16,59 @@ class AnalyticsClient {
|
|||
}
|
||||
|
||||
identifyUser(uuid: string) {
|
||||
this.posthogPromise.then(posthog => {
|
||||
posthog.identify(uuid, { uuid, wa: true });
|
||||
}).catch();
|
||||
this.posthogPromise
|
||||
.then((posthog) => {
|
||||
posthog.identify(uuid, { uuid, wa: true });
|
||||
})
|
||||
.catch();
|
||||
}
|
||||
|
||||
loggedWithSso() {
|
||||
this.posthogPromise.then(posthog => {
|
||||
posthog.capture('wa-logged-sso');
|
||||
}).catch();
|
||||
this.posthogPromise
|
||||
.then((posthog) => {
|
||||
posthog.capture("wa-logged-sso");
|
||||
})
|
||||
.catch();
|
||||
}
|
||||
|
||||
loggedWithToken() {
|
||||
this.posthogPromise.then(posthog => {
|
||||
posthog.capture('wa-logged-token');
|
||||
}).catch();
|
||||
this.posthogPromise
|
||||
.then((posthog) => {
|
||||
posthog.capture("wa-logged-token");
|
||||
})
|
||||
.catch();
|
||||
}
|
||||
|
||||
enteredRoom(roomId: string) {
|
||||
this.posthogPromise.then(posthog => {
|
||||
posthog.capture('$pageView', {roomId});
|
||||
}).catch();
|
||||
this.posthogPromise
|
||||
.then((posthog) => {
|
||||
posthog.capture("$pageView", { roomId });
|
||||
})
|
||||
.catch();
|
||||
}
|
||||
|
||||
openedMenu() {
|
||||
this.posthogPromise.then(posthog => {
|
||||
posthog.capture('wa-opened-menu');
|
||||
}).catch();
|
||||
this.posthogPromise
|
||||
.then((posthog) => {
|
||||
posthog.capture("wa-opened-menu");
|
||||
})
|
||||
.catch();
|
||||
}
|
||||
|
||||
launchEmote(emote: string) {
|
||||
this.posthogPromise.then(posthog => {
|
||||
posthog.capture('wa-emote-launch', {emote});
|
||||
}).catch();
|
||||
this.posthogPromise
|
||||
.then((posthog) => {
|
||||
posthog.capture("wa-emote-launch", { emote });
|
||||
})
|
||||
.catch();
|
||||
}
|
||||
|
||||
enteredJitsi(roomName: string, roomId: string) {
|
||||
this.posthogPromise.then(posthog => {
|
||||
posthog.capture('wa-entered-jitsi', {roomName, roomId});
|
||||
}).catch();
|
||||
this.posthogPromise
|
||||
.then((posthog) => {
|
||||
posthog.capture("wa-entered-jitsi", { roomName, roomId });
|
||||
})
|
||||
.catch();
|
||||
}
|
||||
}
|
||||
export const analyticsClient = new AnalyticsClient();
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<script lang="typescript">
|
||||
import MenuIcon from "./Menu/MenuIcon.svelte";
|
||||
import {menuIconVisiblilityStore, menuVisiblilityStore} from "../Stores/MenuStore";
|
||||
import {emoteMenuVisiblilityStore} from "../Stores/EmoteStore";
|
||||
import {enableCameraSceneVisibilityStore} from "../Stores/MediaStore";
|
||||
import CameraControls from "./CameraControls.svelte";
|
||||
import MyCamera from "./MyCamera.svelte";
|
||||
|
@ -26,6 +27,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 +113,11 @@
|
|||
<Menu></Menu>
|
||||
</div>
|
||||
{/if}
|
||||
{#if $emoteMenuVisiblilityStore}
|
||||
<div>
|
||||
<EmoteMenu></EmoteMenu>
|
||||
</div>
|
||||
{/if}
|
||||
{#if $gameOverlayVisibilityStore}
|
||||
<div>
|
||||
<VideoOverlay></VideoOverlay>
|
||||
|
|
75
front/src/Components/EmoteMenu/EmoteMenu.svelte
Normal file
75
front/src/Components/EmoteMenu/EmoteMenu.svelte
Normal file
|
@ -0,0 +1,75 @@
|
|||
<script lang="typescript">
|
||||
|
||||
import type { Unsubscriber } from "svelte/store";
|
||||
import { emoteStore, emoteMenuStore } from "../../Stores/EmoteStore";
|
||||
import { onDestroy, onMount } from "svelte";
|
||||
import { EmojiButton } from '@joeattardi/emoji-button';
|
||||
import { isMobile } from "../../Enum/EnvironmentVariable";
|
||||
|
||||
let emojiContainer: HTMLElement;
|
||||
let picker: EmojiButton;
|
||||
|
||||
let unsubscriber: Unsubscriber | null = null;
|
||||
|
||||
onMount(() => {
|
||||
picker = new EmojiButton({
|
||||
rootElement: emojiContainer,
|
||||
styleProperties: {
|
||||
'--font': 'Press Start 2P'
|
||||
},
|
||||
emojisPerRow: isMobile() ? 6 : 8,
|
||||
autoFocusSearch: false
|
||||
});
|
||||
|
||||
picker.on("emoji", (selection) => {
|
||||
emoteStore.set(selection.emoji);
|
||||
});
|
||||
|
||||
picker.on("hidden", () => {
|
||||
emoteMenuStore.closeEmoteMenu();
|
||||
});
|
||||
|
||||
unsubscriber = emoteMenuStore.subscribe((isEmoteMenuVisible) => {
|
||||
if (isEmoteMenuVisible && !picker.isPickerVisible()) {
|
||||
picker.showPicker(emojiContainer);
|
||||
} else {
|
||||
picker.hidePicker();
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
function onKeyDown(e:KeyboardEvent) {
|
||||
if (e.key === 'Escape') {
|
||||
emoteMenuStore.closeEmoteMenu();
|
||||
}
|
||||
}
|
||||
|
||||
onDestroy(() => {
|
||||
if (unsubscriber) {
|
||||
unsubscriber();
|
||||
}
|
||||
|
||||
picker.destroyPicker();
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<svelte:window on:keydown={onKeyDown}/>
|
||||
|
||||
<div class="emote-menu-container">
|
||||
<div class="emote-menu" bind:this={emojiContainer}></div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.emote-menu-container {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.emote-menu {
|
||||
pointer-events: all;
|
||||
}
|
||||
</style>
|
|
@ -2,15 +2,15 @@ import { Subject } from "rxjs";
|
|||
|
||||
interface EmoteEvent {
|
||||
userId: number;
|
||||
emoteName: string;
|
||||
emote: string;
|
||||
}
|
||||
|
||||
class EmoteEventStream {
|
||||
private _stream: Subject<EmoteEvent> = new Subject();
|
||||
public stream = this._stream.asObservable();
|
||||
|
||||
fire(userId: number, emoteName: string) {
|
||||
this._stream.next({ userId, emoteName });
|
||||
fire(userId: number, emote: string) {
|
||||
this._stream.next({ userId, emote });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ export const DISPLAY_TERMS_OF_USE = process.env.DISPLAY_TERMS_OF_USE == "true";
|
|||
export const NODE_ENV = process.env.NODE_ENV || "development";
|
||||
export const CONTACT_URL = process.env.CONTACT_URL || undefined;
|
||||
export const PROFILE_URL = process.env.PROFILE_URL || undefined;
|
||||
export const POSTHOG_API_KEY: string = process.env.POSTHOG_API_KEY as string || '';
|
||||
export const POSTHOG_API_KEY: string = (process.env.POSTHOG_API_KEY as string) || "";
|
||||
export const POSTHOG_URL = process.env.POSTHOG_URL || undefined;
|
||||
|
||||
export const isMobile = (): boolean => window.innerWidth <= 800 || window.innerHeight <= 600;
|
||||
|
|
|
@ -32,7 +32,7 @@ export abstract class Character extends Container {
|
|||
//private teleportation: Sprite;
|
||||
private invisible: boolean;
|
||||
public companion?: Companion;
|
||||
private emote: Phaser.GameObjects.Sprite | null = null;
|
||||
private emote: Phaser.GameObjects.Text | null = null;
|
||||
private emoteTween: Phaser.Tweens.Tween | null = null;
|
||||
scene: GameScene;
|
||||
|
||||
|
@ -289,53 +289,48 @@ export abstract class Character extends Container {
|
|||
isSilentStore.set(false);
|
||||
}
|
||||
|
||||
playEmote(emoteKey: string) {
|
||||
playEmote(emote: string) {
|
||||
this.cancelPreviousEmote();
|
||||
|
||||
const scalingFactor = waScaleManager.uiScalingFactor * 0.05;
|
||||
const emoteY = -30 - scalingFactor * 10;
|
||||
|
||||
const emoteY = -45;
|
||||
this.playerName.setVisible(false);
|
||||
this.emote = new Sprite(this.scene, 0, 0, emoteKey);
|
||||
this.emote = new Text(this.scene, -10, 0, emote, { fontFamily: '"twemoji"', fontSize: "20px" });
|
||||
this.emote.setAlpha(0);
|
||||
this.emote.setScale(0.1 * scalingFactor);
|
||||
this.add(this.emote);
|
||||
this.scene.sys.updateList.add(this.emote);
|
||||
|
||||
this.createStartTransition(scalingFactor, emoteY);
|
||||
this.createStartTransition(emoteY);
|
||||
}
|
||||
|
||||
private createStartTransition(scalingFactor: number, emoteY: number) {
|
||||
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) {
|
||||
|
|
|
@ -1,24 +1,7 @@
|
|||
import type { BodyResourceDescriptionInterface } from "../Entity/PlayerTextures";
|
||||
import { emoteEventStream } from "../../Connexion/EmoteEventStream";
|
||||
import type { GameScene } from "./GameScene";
|
||||
import type { RadialMenuItem } from "../Components/RadialMenu";
|
||||
import LoaderPlugin = Phaser.Loader.LoaderPlugin;
|
||||
import type { Subscription } from "rxjs";
|
||||
|
||||
interface RegisteredEmote extends BodyResourceDescriptionInterface {
|
||||
name: string;
|
||||
img: string;
|
||||
}
|
||||
|
||||
export const emotes: { [key: string]: RegisteredEmote } = {
|
||||
"emote-heart": { name: "emote-heart", img: "resources/emotes/heart-emote.png" },
|
||||
"emote-clap": { name: "emote-clap", img: "resources/emotes/clap-emote.png" },
|
||||
"emote-hand": { name: "emote-hand", img: "resources/emotes/hand-emote.png" },
|
||||
"emote-thanks": { name: "emote-thanks", img: "resources/emotes/thanks-emote.png" },
|
||||
"emote-thumb-up": { name: "emote-thumb-up", img: "resources/emotes/thumb-up-emote.png" },
|
||||
"emote-thumb-down": { name: "emote-thumb-down", img: "resources/emotes/thumb-down-emote.png" },
|
||||
};
|
||||
|
||||
export class EmoteManager {
|
||||
private subscription: Subscription;
|
||||
|
||||
|
@ -26,47 +9,10 @@ export class EmoteManager {
|
|||
this.subscription = emoteEventStream.stream.subscribe((event) => {
|
||||
const actor = this.scene.MapPlayersByKey.get(event.userId);
|
||||
if (actor) {
|
||||
this.lazyLoadEmoteTexture(event.emoteName).then((emoteKey) => {
|
||||
actor.playEmote(emoteKey);
|
||||
});
|
||||
actor.playEmote(event.emote);
|
||||
}
|
||||
});
|
||||
}
|
||||
createLoadingPromise(loadPlugin: LoaderPlugin, playerResourceDescriptor: BodyResourceDescriptionInterface) {
|
||||
return new Promise<string>((res) => {
|
||||
if (loadPlugin.textureManager.exists(playerResourceDescriptor.name)) {
|
||||
return res(playerResourceDescriptor.name);
|
||||
}
|
||||
loadPlugin.image(playerResourceDescriptor.name, playerResourceDescriptor.img);
|
||||
loadPlugin.once("filecomplete-image-" + playerResourceDescriptor.name, () =>
|
||||
res(playerResourceDescriptor.name)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
lazyLoadEmoteTexture(textureKey: string): Promise<string> {
|
||||
const emoteDescriptor = emotes[textureKey];
|
||||
if (emoteDescriptor === undefined) {
|
||||
throw "Emote not found!";
|
||||
}
|
||||
const loadPromise = this.createLoadingPromise(this.scene.load, emoteDescriptor);
|
||||
this.scene.load.start();
|
||||
return loadPromise;
|
||||
}
|
||||
|
||||
getMenuImages(): Promise<RadialMenuItem[]> {
|
||||
const promises = [];
|
||||
for (const key in emotes) {
|
||||
const promise = this.lazyLoadEmoteTexture(key).then((textureKey) => {
|
||||
return {
|
||||
image: textureKey,
|
||||
name: textureKey,
|
||||
};
|
||||
});
|
||||
promises.push(promise);
|
||||
}
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.subscription.unsubscribe();
|
||||
|
|
|
@ -9,6 +9,7 @@ import { get } from "svelte/store";
|
|||
import { requestedCameraState, requestedMicrophoneState } from "../../Stores/MediaStore";
|
||||
import { helpCameraSettingsVisibleStore } from "../../Stores/HelpCameraSettingsStore";
|
||||
import { menuIconVisiblilityStore } from "../../Stores/MenuStore";
|
||||
import { emoteMenuVisiblilityStore } from "../../Stores/EmoteStore";
|
||||
|
||||
/**
|
||||
* This class should be responsible for any scene starting/stopping
|
||||
|
@ -111,6 +112,7 @@ export class GameManager {
|
|||
public gameSceneIsCreated(scene: GameScene) {
|
||||
this.currentGameSceneName = scene.scene.key;
|
||||
menuIconVisiblilityStore.set(true);
|
||||
emoteMenuVisiblilityStore.set(true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -123,6 +125,7 @@ export class GameManager {
|
|||
gameScene.cleanupClosingScene();
|
||||
gameScene.createSuccessorGameScene(false, false);
|
||||
menuIconVisiblilityStore.set(false);
|
||||
emoteMenuVisiblilityStore.set(false);
|
||||
if (!this.scenePlugin.get(targetSceneName)) {
|
||||
this.scenePlugin.add(targetSceneName, sceneClass, false);
|
||||
}
|
||||
|
@ -136,6 +139,7 @@ export class GameManager {
|
|||
if (this.currentGameSceneName) {
|
||||
this.scenePlugin.start(this.currentGameSceneName);
|
||||
menuIconVisiblilityStore.set(true);
|
||||
emoteMenuVisiblilityStore.set(true);
|
||||
} else {
|
||||
this.scenePlugin.run(fallbackSceneName);
|
||||
}
|
||||
|
|
|
@ -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, emoteMenuStore } from "../../Stores/EmoteStore";
|
||||
import {
|
||||
audioManagerFileStore,
|
||||
audioManagerVisibilityStore,
|
||||
|
@ -93,8 +94,8 @@ 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 {analyticsClient} from "../../Administration/AnalyticsClient";
|
||||
import { analyticsClient } from "../../Administration/AnalyticsClient";
|
||||
import { get } from "svelte/store";
|
||||
|
||||
export interface GameSceneInitInterface {
|
||||
initPosition: PointInterface | null;
|
||||
|
@ -172,6 +173,8 @@ export class GameScene extends DirtyScene {
|
|||
private iframeSubscriptionList!: Array<Subscription>;
|
||||
private peerStoreUnsubscribe!: () => void;
|
||||
private chatVisibilityUnsubscribe!: () => void;
|
||||
private emoteUnsubscribe!: () => void;
|
||||
private emoteMenuUnsubscribe!: () => void;
|
||||
private biggestAvailableAreaStoreUnsubscribe!: () => void;
|
||||
MapUrlFile: string;
|
||||
roomUrl: string;
|
||||
|
@ -616,6 +619,22 @@ export class GameScene extends DirtyScene {
|
|||
this.openChatIcon.setVisible(!v);
|
||||
});
|
||||
|
||||
this.emoteUnsubscribe = emoteStore.subscribe((emoteKey) => {
|
||||
if (emoteKey) {
|
||||
this.CurrentPlayer?.playEmote(emoteKey);
|
||||
this.connection?.emitEmoteEvent(emoteKey);
|
||||
emoteStore.set(null);
|
||||
}
|
||||
});
|
||||
|
||||
this.emoteMenuUnsubscribe = emoteMenuStore.subscribe((emoteMenu) => {
|
||||
if (emoteMenu) {
|
||||
this.userInputManager.disableControls();
|
||||
} else {
|
||||
this.userInputManager.restoreControls();
|
||||
}
|
||||
});
|
||||
|
||||
Promise.all([this.connectionAnswerPromise as Promise<unknown>, ...scriptPromises]).then(() => {
|
||||
this.scene.wake();
|
||||
});
|
||||
|
@ -1306,6 +1325,8 @@ ${escapedMessage}
|
|||
this.emoteManager.destroy();
|
||||
this.peerStoreUnsubscribe();
|
||||
this.chatVisibilityUnsubscribe();
|
||||
this.emoteUnsubscribe();
|
||||
this.emoteMenuUnsubscribe();
|
||||
this.biggestAvailableAreaStoreUnsubscribe();
|
||||
iframeListener.unregisterAnswerer("getState");
|
||||
iframeListener.unregisterAnswerer("loadTileset");
|
||||
|
@ -1436,9 +1457,13 @@ ${escapedMessage}
|
|||
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.
|
||||
}
|
||||
this.emoteManager
|
||||
.getMenuImages()
|
||||
.then((emoteMenuElements) => this.CurrentPlayer.openOrCloseEmoteMenu(emoteMenuElements));
|
||||
|
||||
// toggle EmoteMenu
|
||||
if (get(emoteMenuStore)) {
|
||||
emoteMenuStore.closeEmoteMenu();
|
||||
} else {
|
||||
emoteMenuStore.openEmoteMenu();
|
||||
}
|
||||
});
|
||||
this.CurrentPlayer.on(requestEmoteEventName, (emoteKey: string) => {
|
||||
this.connection?.emitEmoteEvent(emoteKey);
|
||||
|
|
|
@ -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 { RadialMenu, RadialMenuClickEvent, RadialMenuItem } from "../Components/RadialMenu";
|
||||
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: RadialMenu | 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 {
|
||||
|
@ -93,40 +84,4 @@ export class Player extends Character {
|
|||
public isMoving(): boolean {
|
||||
return this.wasMoving;
|
||||
}
|
||||
|
||||
openOrCloseEmoteMenu(emotes: RadialMenuItem[]) {
|
||||
if (this.emoteMenu) {
|
||||
this.closeEmoteMenu();
|
||||
} else {
|
||||
this.openEmoteMenu(emotes);
|
||||
}
|
||||
}
|
||||
|
||||
openEmoteMenu(emotes: RadialMenuItem[]): void {
|
||||
this.cancelPreviousEmote();
|
||||
this.emoteMenu = new RadialMenu(this.scene, this.x, this.y, emotes);
|
||||
this.emoteMenu.on(RadialMenuClickEvent, (item: RadialMenuItem) => {
|
||||
this.closeEmoteMenu();
|
||||
this.emit(requestEmoteEventName, item.name);
|
||||
this.playEmote(item.name);
|
||||
});
|
||||
}
|
||||
|
||||
isSilent() {
|
||||
super.isSilent();
|
||||
}
|
||||
noSilent() {
|
||||
super.noSilent();
|
||||
}
|
||||
|
||||
closeEmoteMenu(): void {
|
||||
if (!this.emoteMenu) return;
|
||||
this.emoteMenu.destroy();
|
||||
this.emoteMenu = null;
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.scene.events.removeListener("postupdate", this.updateListener);
|
||||
super.destroy();
|
||||
}
|
||||
}
|
||||
|
|
19
front/src/Stores/EmoteStore.ts
Normal file
19
front/src/Stores/EmoteStore.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
import { writable } from "svelte/store";
|
||||
|
||||
function createEmoteMenuStore() {
|
||||
const { subscribe, set } = writable(false);
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
openEmoteMenu() {
|
||||
set(true);
|
||||
},
|
||||
closeEmoteMenu() {
|
||||
set(false);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export const emoteMenuVisiblilityStore = writable(false);
|
||||
export const emoteStore = writable<string | null>(null);
|
||||
export const emoteMenuStore = createEmoteMenuStore();
|
|
@ -2,13 +2,13 @@ import { get, writable } from "svelte/store";
|
|||
import Timeout = NodeJS.Timeout;
|
||||
import { userIsAdminStore } from "./GameStore";
|
||||
import { CONTACT_URL } from "../Enum/EnvironmentVariable";
|
||||
import {analyticsClient} from "../Administration/AnalyticsClient";
|
||||
import { analyticsClient } from "../Administration/AnalyticsClient";
|
||||
|
||||
export const menuIconVisiblilityStore = writable(false);
|
||||
export const menuVisiblilityStore = writable(false);
|
||||
menuVisiblilityStore.subscribe((value) => {
|
||||
if (value) analyticsClient.openedMenu();
|
||||
})
|
||||
});
|
||||
export const menuInputFocusStore = writable(false);
|
||||
export const userIsConnected = writable(false);
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ import { Game } from "./Phaser/Game/Game";
|
|||
import App from "./Components/App.svelte";
|
||||
import { HtmlUtils } from "./WebRtc/HtmlUtils";
|
||||
import WebGLRenderer = Phaser.Renderer.WebGL.WebGLRenderer;
|
||||
import {analyticsClient} from "./Administration/AnalyticsClient";
|
||||
import { analyticsClient } from "./Administration/AnalyticsClient";
|
||||
|
||||
const { width, height } = coWebsiteManager.getGameSize();
|
||||
const valueGameQuality = localUserStore.getGameQualityValue();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue