2020-06-23 12:24:36 +02:00
|
|
|
import {gameManager} from "../Game/GameManager";
|
|
|
|
import {TextField} from "../Components/TextField";
|
|
|
|
import Image = Phaser.GameObjects.Image;
|
2020-09-25 18:29:22 +02:00
|
|
|
import {mediaManager} from "../../WebRtc/MediaManager";
|
2020-06-23 12:24:36 +02:00
|
|
|
import {SoundMeter} from "../Components/SoundMeter";
|
|
|
|
import {SoundMeterSprite} from "../Components/SoundMeterSprite";
|
2020-10-25 19:38:00 +01:00
|
|
|
import {HtmlUtils} from "../../WebRtc/HtmlUtils";
|
2021-04-14 17:47:26 +02:00
|
|
|
import {touchScreenManager} from "../../Touch/TouchScreenManager";
|
|
|
|
import {PinchManager} from "../UserInput/PinchManager";
|
2021-04-21 18:27:33 +02:00
|
|
|
import Zone = Phaser.GameObjects.Zone;
|
2021-04-22 11:26:35 +02:00
|
|
|
import { MenuScene } from "../Menu/MenuScene";
|
2021-05-05 17:07:03 +02:00
|
|
|
import {ResizableScene} from "./ResizableScene";
|
2021-05-18 16:38:56 +02:00
|
|
|
import {
|
|
|
|
audioConstraintStore,
|
|
|
|
enableCameraSceneVisibilityStore,
|
|
|
|
localStreamStore,
|
|
|
|
mediaStreamConstraintsStore,
|
|
|
|
videoConstraintStore
|
|
|
|
} from "../../Stores/MediaStore";
|
|
|
|
import type {Unsubscriber} from "svelte/store";
|
2020-06-23 12:24:36 +02:00
|
|
|
|
|
|
|
export const EnableCameraSceneName = "EnableCameraScene";
|
|
|
|
enum LoginTextures {
|
|
|
|
playButton = "play_button",
|
|
|
|
icon = "icon",
|
|
|
|
mainFont = "main_font",
|
|
|
|
arrowRight = "arrow_right",
|
|
|
|
arrowUp = "arrow_up"
|
|
|
|
}
|
|
|
|
|
2021-04-22 11:26:35 +02:00
|
|
|
const enableCameraSceneKey = 'enableCameraScene';
|
2021-02-02 17:31:44 +01:00
|
|
|
|
2021-05-05 17:07:03 +02:00
|
|
|
export class EnableCameraScene extends ResizableScene {
|
2020-08-07 23:39:06 +02:00
|
|
|
private textField!: TextField;
|
|
|
|
private cameraNameField!: TextField;
|
|
|
|
private arrowLeft!: Image;
|
|
|
|
private arrowRight!: Image;
|
|
|
|
private arrowDown!: Image;
|
|
|
|
private arrowUp!: Image;
|
2020-06-25 09:28:00 +02:00
|
|
|
private microphonesList: MediaDeviceInfo[] = new Array<MediaDeviceInfo>();
|
|
|
|
private camerasList: MediaDeviceInfo[] = new Array<MediaDeviceInfo>();
|
2020-06-23 12:24:36 +02:00
|
|
|
private cameraSelected: number = 0;
|
|
|
|
private microphoneSelected: number = 0;
|
|
|
|
private soundMeter: SoundMeter;
|
2020-08-07 23:39:06 +02:00
|
|
|
private soundMeterSprite!: SoundMeterSprite;
|
|
|
|
private microphoneNameField!: TextField;
|
2020-06-23 12:24:36 +02:00
|
|
|
|
2021-04-22 11:26:35 +02:00
|
|
|
private enableCameraSceneElement!: Phaser.GameObjects.DOMElement;
|
|
|
|
|
2021-04-21 18:27:33 +02:00
|
|
|
private mobileTapZone!: Zone;
|
2021-05-18 16:38:56 +02:00
|
|
|
private localStreamStoreUnsubscriber!: Unsubscriber;
|
2021-05-05 12:15:13 +02:00
|
|
|
|
2020-06-23 12:24:36 +02:00
|
|
|
constructor() {
|
|
|
|
super({
|
|
|
|
key: EnableCameraSceneName
|
|
|
|
});
|
|
|
|
this.soundMeter = new SoundMeter();
|
|
|
|
}
|
|
|
|
|
|
|
|
preload() {
|
2021-04-22 11:26:35 +02:00
|
|
|
|
|
|
|
this.load.html(enableCameraSceneKey, 'resources/html/EnableCameraScene.html');
|
|
|
|
|
2020-06-23 12:24:36 +02:00
|
|
|
this.load.image(LoginTextures.playButton, "resources/objects/play_button.png");
|
|
|
|
this.load.image(LoginTextures.arrowRight, "resources/objects/arrow_right.png");
|
|
|
|
this.load.image(LoginTextures.arrowUp, "resources/objects/arrow_up.png");
|
|
|
|
// Note: arcade.png from the Phaser 3 examples at: https://github.com/photonstorm/phaser3-examples/tree/master/public/assets/fonts/bitmap
|
|
|
|
this.load.bitmapFont(LoginTextures.mainFont, 'resources/fonts/arcade.png', 'resources/fonts/arcade.xml');
|
|
|
|
}
|
|
|
|
|
|
|
|
create() {
|
2021-04-22 11:26:35 +02:00
|
|
|
|
2021-05-05 17:07:03 +02:00
|
|
|
this.enableCameraSceneElement = this.add.dom(-1000, 0).createFromCache(enableCameraSceneKey);
|
|
|
|
this.centerXDomElement(this.enableCameraSceneElement, 300);
|
|
|
|
|
2021-04-22 11:26:35 +02:00
|
|
|
MenuScene.revealMenusAfterInit(this.enableCameraSceneElement, enableCameraSceneKey);
|
|
|
|
|
|
|
|
const continuingButton = this.enableCameraSceneElement.getChildByID('enableCameraSceneFormSubmit') as HTMLButtonElement;
|
|
|
|
continuingButton.addEventListener('click', (e) => {
|
|
|
|
e.preventDefault();
|
|
|
|
this.login();
|
|
|
|
});
|
|
|
|
|
2021-04-14 17:47:26 +02:00
|
|
|
if (touchScreenManager.supportTouchScreen) {
|
|
|
|
new PinchManager(this);
|
|
|
|
}
|
2021-04-21 18:01:26 +02:00
|
|
|
//this.scale.setZoom(ZOOM_LEVEL);
|
|
|
|
//Phaser.Display.Align.In.BottomCenter(this.pressReturnField, zone);
|
2020-06-23 12:24:36 +02:00
|
|
|
|
2021-04-22 11:26:35 +02:00
|
|
|
/* FIX ME */
|
2021-05-05 11:01:11 +02:00
|
|
|
this.textField = new TextField(this, this.scale.width / 2, 20, '');
|
2020-06-23 12:24:36 +02:00
|
|
|
|
2021-02-03 23:22:23 +01:00
|
|
|
// For mobile purposes - we need a big enough touchable area.
|
2021-05-05 11:01:11 +02:00
|
|
|
this.mobileTapZone = this.add.zone(this.scale.width / 2,this.scale.height - 30,200,50)
|
2021-04-21 18:27:33 +02:00
|
|
|
.setInteractive().on("pointerdown", () => {
|
2021-02-03 23:22:23 +01:00
|
|
|
this.login();
|
|
|
|
});
|
2020-06-23 12:24:36 +02:00
|
|
|
|
|
|
|
this.cameraNameField = new TextField(this, this.game.renderer.width / 2, this.game.renderer.height - 60, '');
|
|
|
|
|
|
|
|
this.microphoneNameField = new TextField(this, this.game.renderer.width / 2, this.game.renderer.height - 40, '');
|
|
|
|
|
|
|
|
this.arrowRight = new Image(this, 0, 0, LoginTextures.arrowRight);
|
|
|
|
this.arrowRight.setVisible(false);
|
2020-06-24 17:29:23 +02:00
|
|
|
this.arrowRight.setInteractive().on('pointerdown', this.nextCam.bind(this));
|
2020-06-23 12:24:36 +02:00
|
|
|
this.add.existing(this.arrowRight);
|
|
|
|
|
|
|
|
this.arrowLeft = new Image(this, 0, 0, LoginTextures.arrowRight);
|
|
|
|
this.arrowLeft.setVisible(false);
|
|
|
|
this.arrowLeft.flipX = true;
|
2020-06-24 17:29:23 +02:00
|
|
|
this.arrowLeft.setInteractive().on('pointerdown', this.previousCam.bind(this));
|
2020-06-23 12:24:36 +02:00
|
|
|
this.add.existing(this.arrowLeft);
|
|
|
|
|
|
|
|
this.arrowUp = new Image(this, 0, 0, LoginTextures.arrowUp);
|
|
|
|
this.arrowUp.setVisible(false);
|
2020-06-24 17:29:23 +02:00
|
|
|
this.arrowUp.setInteractive().on('pointerdown', this.previousMic.bind(this));
|
2020-06-23 12:24:36 +02:00
|
|
|
this.add.existing(this.arrowUp);
|
|
|
|
|
|
|
|
this.arrowDown = new Image(this, 0, 0, LoginTextures.arrowUp);
|
|
|
|
this.arrowDown.setVisible(false);
|
|
|
|
this.arrowDown.flipY = true;
|
2020-06-24 17:29:23 +02:00
|
|
|
this.arrowDown.setInteractive().on('pointerdown', this.nextMic.bind(this));
|
2020-06-23 12:24:36 +02:00
|
|
|
this.add.existing(this.arrowDown);
|
|
|
|
|
|
|
|
this.input.keyboard.on('keyup-ENTER', () => {
|
2020-10-08 18:51:24 +02:00
|
|
|
this.login();
|
2020-06-23 12:24:36 +02:00
|
|
|
});
|
|
|
|
|
2020-10-25 19:38:00 +01:00
|
|
|
HtmlUtils.getElementByIdOrFail<HTMLDivElement>('webRtcSetup').classList.add('active');
|
2020-06-23 12:24:36 +02:00
|
|
|
|
2021-05-18 16:38:56 +02:00
|
|
|
this.localStreamStoreUnsubscriber = localStreamStore.subscribe((result) => {
|
|
|
|
if (result.type === 'error') {
|
|
|
|
// TODO: proper handling of the error
|
|
|
|
throw result.error;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.getDevices();
|
|
|
|
if (result.stream !== null) {
|
|
|
|
this.setupStream(result.stream);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
/*const mediaPromise = mediaManager.getCamera();
|
2020-06-23 12:24:36 +02:00
|
|
|
mediaPromise.then(this.getDevices.bind(this));
|
2021-05-18 16:38:56 +02:00
|
|
|
mediaPromise.then(this.setupStream.bind(this));*/
|
2020-06-23 12:24:36 +02:00
|
|
|
|
2020-06-24 17:29:23 +02:00
|
|
|
this.input.keyboard.on('keydown-RIGHT', this.nextCam.bind(this));
|
|
|
|
this.input.keyboard.on('keydown-LEFT', this.previousCam.bind(this));
|
|
|
|
this.input.keyboard.on('keydown-DOWN', this.nextMic.bind(this));
|
|
|
|
this.input.keyboard.on('keydown-UP', this.previousMic.bind(this));
|
2020-06-23 12:24:36 +02:00
|
|
|
|
|
|
|
this.soundMeterSprite = new SoundMeterSprite(this, 50, 50);
|
|
|
|
this.soundMeterSprite.setVisible(false);
|
|
|
|
this.add.existing(this.soundMeterSprite);
|
2020-06-24 17:29:23 +02:00
|
|
|
|
2021-05-05 17:07:03 +02:00
|
|
|
this.onResize();
|
2021-05-18 16:38:56 +02:00
|
|
|
|
|
|
|
enableCameraSceneVisibilityStore.showEnableCameraScene();
|
2020-06-24 17:29:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private previousCam(): void {
|
2020-06-25 10:43:42 +02:00
|
|
|
if (this.cameraSelected === 0 || this.camerasList.length === 0) {
|
2020-06-24 17:29:23 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.cameraSelected--;
|
2021-05-18 16:38:56 +02:00
|
|
|
videoConstraintStore.setDeviceId(this.camerasList[this.cameraSelected].deviceId);
|
|
|
|
|
|
|
|
//mediaManager.setCamera(this.camerasList[this.cameraSelected].deviceId).then(this.setupStream.bind(this));
|
2020-06-24 17:29:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private nextCam(): void {
|
2020-06-25 10:43:42 +02:00
|
|
|
if (this.cameraSelected === this.camerasList.length - 1 || this.camerasList.length === 0) {
|
2020-06-24 17:29:23 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.cameraSelected++;
|
2021-05-18 16:38:56 +02:00
|
|
|
videoConstraintStore.setDeviceId(this.camerasList[this.cameraSelected].deviceId);
|
|
|
|
|
2020-06-24 17:29:23 +02:00
|
|
|
// TODO: the change of camera should be OBSERVED (reactive)
|
2021-05-18 16:38:56 +02:00
|
|
|
//mediaManager.setCamera(this.camerasList[this.cameraSelected].deviceId).then(this.setupStream.bind(this));
|
2020-06-24 17:29:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private previousMic(): void {
|
2020-06-25 10:43:42 +02:00
|
|
|
if (this.microphoneSelected === 0 || this.microphonesList.length === 0) {
|
2020-06-24 17:29:23 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.microphoneSelected--;
|
2021-05-18 16:38:56 +02:00
|
|
|
audioConstraintStore.setDeviceId(this.microphonesList[this.microphoneSelected].deviceId);
|
|
|
|
//mediaManager.setMicrophone(this.microphonesList[this.microphoneSelected].deviceId).then(this.setupStream.bind(this));
|
2020-06-24 17:29:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private nextMic(): void {
|
2020-06-25 10:43:42 +02:00
|
|
|
if (this.microphoneSelected === this.microphonesList.length - 1 || this.microphonesList.length === 0) {
|
2020-06-24 17:29:23 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.microphoneSelected++;
|
2021-05-18 16:38:56 +02:00
|
|
|
audioConstraintStore.setDeviceId(this.microphonesList[this.microphoneSelected].deviceId);
|
2020-06-24 17:29:23 +02:00
|
|
|
// TODO: the change of camera should be OBSERVED (reactive)
|
2021-05-18 16:38:56 +02:00
|
|
|
//mediaManager.setMicrophone(this.microphonesList[this.microphoneSelected].deviceId).then(this.setupStream.bind(this));
|
2020-06-23 12:24:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Function called each time a camera is changed
|
|
|
|
*/
|
|
|
|
private setupStream(stream: MediaStream): void {
|
2020-10-25 19:38:00 +01:00
|
|
|
const img = HtmlUtils.getElementByIdOrFail<HTMLDivElement>('webRtcSetupNoVideo');
|
2020-06-23 12:24:36 +02:00
|
|
|
img.style.display = 'none';
|
|
|
|
|
2020-10-25 19:38:00 +01:00
|
|
|
const div = HtmlUtils.getElementByIdOrFail<HTMLVideoElement>('myCamVideoSetup');
|
2020-06-23 12:24:36 +02:00
|
|
|
div.srcObject = stream;
|
|
|
|
|
|
|
|
this.soundMeter.connectToSource(stream, new window.AudioContext());
|
2020-06-24 17:46:41 +02:00
|
|
|
this.soundMeterSprite.setVisible(true);
|
2020-06-23 12:24:36 +02:00
|
|
|
|
|
|
|
this.updateWebCamName();
|
|
|
|
}
|
|
|
|
|
|
|
|
private updateWebCamName(): void {
|
|
|
|
if (this.camerasList.length > 1) {
|
|
|
|
let label = this.camerasList[this.cameraSelected].label;
|
|
|
|
// remove text in parenthesis
|
|
|
|
label = label.replace(/\([^()]*\)/g, '').trim();
|
|
|
|
// remove accents
|
|
|
|
label = label.normalize("NFD").replace(/[\u0300-\u036f]/g, "");
|
|
|
|
this.cameraNameField.text = label;
|
|
|
|
|
2021-03-11 16:14:34 +01:00
|
|
|
this.arrowRight.setVisible(this.cameraSelected < this.camerasList.length - 1);
|
|
|
|
this.arrowLeft.setVisible(this.cameraSelected > 0);
|
2020-06-23 12:24:36 +02:00
|
|
|
}
|
|
|
|
if (this.microphonesList.length > 1) {
|
|
|
|
let label = this.microphonesList[this.microphoneSelected].label;
|
|
|
|
// remove text in parenthesis
|
|
|
|
label = label.replace(/\([^()]*\)/g, '').trim();
|
|
|
|
// remove accents
|
|
|
|
label = label.normalize("NFD").replace(/[\u0300-\u036f]/g, "");
|
|
|
|
|
|
|
|
this.microphoneNameField.text = label;
|
|
|
|
|
2021-03-11 16:14:34 +01:00
|
|
|
this.arrowDown.setVisible(this.microphoneSelected < this.microphonesList.length - 1);
|
|
|
|
this.arrowUp.setVisible(this.microphoneSelected > 0);
|
2020-06-23 12:24:36 +02:00
|
|
|
|
|
|
|
}
|
2020-06-24 17:29:23 +02:00
|
|
|
}
|
|
|
|
|
2021-05-05 17:07:03 +02:00
|
|
|
public onResize(): void {
|
2020-10-25 19:38:00 +01:00
|
|
|
let div = HtmlUtils.getElementByIdOrFail<HTMLVideoElement>('myCamVideoSetup');
|
2020-06-24 17:46:41 +02:00
|
|
|
let bounds = div.getBoundingClientRect();
|
|
|
|
if (!div.srcObject) {
|
2020-10-25 19:38:00 +01:00
|
|
|
div = HtmlUtils.getElementByIdOrFail<HTMLVideoElement>('webRtcSetup');
|
2020-06-24 17:46:41 +02:00
|
|
|
bounds = div.getBoundingClientRect();
|
|
|
|
}
|
2020-06-24 17:29:23 +02:00
|
|
|
|
2020-06-24 18:09:59 +02:00
|
|
|
this.textField.x = this.game.renderer.width / 2;
|
2021-04-21 18:27:33 +02:00
|
|
|
this.mobileTapZone.x = this.game.renderer.width / 2;
|
2020-06-24 18:09:59 +02:00
|
|
|
this.cameraNameField.x = this.game.renderer.width / 2;
|
|
|
|
this.microphoneNameField.x = this.game.renderer.width / 2;
|
|
|
|
|
2021-05-05 17:07:03 +02:00
|
|
|
this.cameraNameField.y = bounds.top / this.scale.zoom - 8;
|
2020-06-24 17:29:23 +02:00
|
|
|
|
|
|
|
this.soundMeterSprite.x = this.game.renderer.width / 2 - this.soundMeterSprite.getWidth() / 2;
|
2021-05-05 17:07:03 +02:00
|
|
|
this.soundMeterSprite.y = bounds.bottom / this.scale.zoom + 16;
|
2020-06-24 17:29:23 +02:00
|
|
|
|
|
|
|
this.microphoneNameField.y = this.soundMeterSprite.y + 22;
|
|
|
|
|
2021-05-05 17:07:03 +02:00
|
|
|
this.arrowRight.x = bounds.right / this.scale.zoom + 16;
|
|
|
|
this.arrowRight.y = (bounds.top + bounds.height / 2) / this.scale.zoom;
|
2020-06-24 17:29:23 +02:00
|
|
|
|
2021-05-05 17:07:03 +02:00
|
|
|
this.arrowLeft.x = bounds.left / this.scale.zoom - 16;
|
|
|
|
this.arrowLeft.y = (bounds.top + bounds.height / 2) / this.scale.zoom;
|
2020-06-24 17:29:23 +02:00
|
|
|
|
|
|
|
this.arrowDown.x = this.microphoneNameField.x + this.microphoneNameField.width / 2 + 16;
|
|
|
|
this.arrowDown.y = this.microphoneNameField.y;
|
|
|
|
|
|
|
|
this.arrowUp.x = this.microphoneNameField.x - this.microphoneNameField.width / 2 - 16;
|
|
|
|
this.arrowUp.y = this.microphoneNameField.y;
|
2021-05-05 15:46:02 +02:00
|
|
|
|
|
|
|
const actionBtn = document.querySelector<HTMLDivElement>('#enableCameraScene .action');
|
|
|
|
if (actionBtn !== null) {
|
|
|
|
actionBtn.style.top = (this.scale.height - 65) + 'px';
|
|
|
|
}
|
2020-06-23 12:24:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
update(time: number, delta: number): void {
|
|
|
|
this.soundMeterSprite.setVolume(this.soundMeter.getVolume());
|
2021-04-22 11:26:35 +02:00
|
|
|
|
2021-05-05 17:07:03 +02:00
|
|
|
this.centerXDomElement(this.enableCameraSceneElement, 300);
|
2020-06-23 12:24:36 +02:00
|
|
|
}
|
|
|
|
|
2021-03-19 11:50:53 +01:00
|
|
|
private login(): void {
|
|
|
|
HtmlUtils.getElementByIdOrFail<HTMLDivElement>('webRtcSetup').style.display = 'none';
|
|
|
|
this.soundMeter.stop();
|
|
|
|
|
2021-05-18 16:38:56 +02:00
|
|
|
enableCameraSceneVisibilityStore.hideEnableCameraScene();
|
|
|
|
this.localStreamStoreUnsubscriber();
|
|
|
|
//mediaManager.stopCamera();
|
|
|
|
//mediaManager.stopMicrophone();
|
2021-03-19 11:50:53 +01:00
|
|
|
|
2021-05-18 16:38:56 +02:00
|
|
|
this.scene.sleep(EnableCameraSceneName);
|
2021-03-19 11:50:53 +01:00
|
|
|
gameManager.goToStartingMap(this.scene);
|
2020-06-23 12:24:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private async getDevices() {
|
2021-05-18 16:38:56 +02:00
|
|
|
// TODO: switch this in a store.
|
2020-06-23 12:24:36 +02:00
|
|
|
const mediaDeviceInfos = await navigator.mediaDevices.enumerateDevices();
|
2021-05-18 16:38:56 +02:00
|
|
|
this.microphonesList = [];
|
|
|
|
this.camerasList = [];
|
2020-06-23 12:24:36 +02:00
|
|
|
for (const mediaDeviceInfo of mediaDeviceInfos) {
|
2020-06-25 09:28:00 +02:00
|
|
|
if (mediaDeviceInfo.kind === 'audioinput') {
|
|
|
|
this.microphonesList.push(mediaDeviceInfo);
|
|
|
|
} else if (mediaDeviceInfo.kind === 'videoinput') {
|
|
|
|
this.camerasList.push(mediaDeviceInfo);
|
2020-06-23 12:24:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
this.updateWebCamName();
|
|
|
|
}
|
|
|
|
}
|