Merge branch 'twemojiEmoteMenu' of github.com:Lurkars/workadventure into twemojiEmoteMenuSvelte
This commit is contained in:
commit
d23820227e
10 changed files with 225 additions and 89 deletions
62
front/src/Phaser/Components/EmoteMenu.ts
Normal file
62
front/src/Phaser/Components/EmoteMenu.ts
Normal file
|
@ -0,0 +1,62 @@
|
|||
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();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
@ -282,26 +282,16 @@ export abstract class Character extends Container {
|
|||
super.destroy();
|
||||
}
|
||||
|
||||
isSilent() {
|
||||
isSilentStore.set(true);
|
||||
}
|
||||
noSilent() {
|
||||
isSilentStore.set(false);
|
||||
}
|
||||
|
||||
playEmote(emoteKey: string) {
|
||||
playEmote(emote: string) {
|
||||
this.cancelPreviousEmote();
|
||||
|
||||
const scalingFactor = waScaleManager.uiScalingFactor * 0.05;
|
||||
const emoteY = -30 - scalingFactor * 10;
|
||||
const scalingFactor = waScaleManager.uiScalingFactor;
|
||||
const emoteY = -60;
|
||||
|
||||
this.playerName.setVisible(false);
|
||||
this.emote = new Sprite(this.scene, 0, 0, emoteKey);
|
||||
this.emote = new Text(this.scene, -12, 0, emote, { fontFamily: '"Twemoji Mozilla"', fontSize: "24px" });
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -1432,9 +1432,8 @@ ${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));
|
||||
|
||||
this.CurrentPlayer.openOrCloseEmoteMenu();
|
||||
});
|
||||
this.CurrentPlayer.on(requestEmoteEventName, (emoteKey: string) => {
|
||||
this.connection?.emitEmoteEvent(emoteKey);
|
||||
|
|
|
@ -3,7 +3,7 @@ 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 { EmoteMenu, EmoteMenuClickEvent } from "../Components/EmoteMenu";
|
||||
|
||||
export const hasMovedEventName = "hasMoved";
|
||||
export const requestEmoteEventName = "requestEmote";
|
||||
|
@ -11,7 +11,7 @@ export const requestEmoteEventName = "requestEmote";
|
|||
export class Player extends Character {
|
||||
private previousDirection: string = PlayerAnimationDirections.Down;
|
||||
private wasMoving: boolean = false;
|
||||
private emoteMenu: RadialMenu | null = null;
|
||||
private emoteMenu: EmoteMenu | null = null;
|
||||
private updateListener: () => void;
|
||||
|
||||
constructor(
|
||||
|
@ -94,21 +94,26 @@ export class Player extends Character {
|
|||
return this.wasMoving;
|
||||
}
|
||||
|
||||
openOrCloseEmoteMenu(emotes: RadialMenuItem[]) {
|
||||
if (this.emoteMenu) {
|
||||
openOrCloseEmoteMenu() {
|
||||
if (!this.emoteMenu) {
|
||||
this.emoteMenu = new EmoteMenu(this.scene, this.x, this.y, this.userInputManager);
|
||||
}
|
||||
|
||||
if (this.emoteMenu.isOpen()) {
|
||||
this.closeEmoteMenu();
|
||||
} else {
|
||||
this.openEmoteMenu(emotes);
|
||||
this.openEmoteMenu();
|
||||
}
|
||||
}
|
||||
|
||||
openEmoteMenu(emotes: RadialMenuItem[]): void {
|
||||
openEmoteMenu(): void {
|
||||
this.cancelPreviousEmote();
|
||||
this.emoteMenu = new RadialMenu(this.scene, this.x, this.y, emotes);
|
||||
this.emoteMenu.on(RadialMenuClickEvent, (item: RadialMenuItem) => {
|
||||
if (!this.emoteMenu) return;
|
||||
this.emoteMenu.openPicker();
|
||||
this.emoteMenu.on(EmoteMenuClickEvent, (emote: string) => {
|
||||
this.closeEmoteMenu();
|
||||
this.emit(requestEmoteEventName, item.name);
|
||||
this.playEmote(item.name);
|
||||
this.emit(requestEmoteEventName, emote);
|
||||
this.playEmote(emote);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -121,8 +126,7 @@ export class Player extends Character {
|
|||
|
||||
closeEmoteMenu(): void {
|
||||
if (!this.emoteMenu) return;
|
||||
this.emoteMenu.destroy();
|
||||
this.emoteMenu = null;
|
||||
this.emoteMenu.closePicker();
|
||||
}
|
||||
|
||||
destroy() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue