diff --git a/front/dist/resources/html/helpCameraSettings.html b/front/dist/resources/html/helpCameraSettings.html new file mode 100644 index 00000000..6ec6fbac --- /dev/null +++ b/front/dist/resources/html/helpCameraSettings.html @@ -0,0 +1,109 @@ + + + diff --git a/front/dist/resources/objects/help-setting-camera-permission.png b/front/dist/resources/objects/help-setting-camera-permission.png new file mode 100644 index 00000000..833499cd Binary files /dev/null and b/front/dist/resources/objects/help-setting-camera-permission.png differ diff --git a/front/src/Phaser/Login/EnableCameraScene.ts b/front/src/Phaser/Login/EnableCameraScene.ts index 321eabed..dffe1042 100644 --- a/front/src/Phaser/Login/EnableCameraScene.ts +++ b/front/src/Phaser/Login/EnableCameraScene.ts @@ -1,8 +1,6 @@ import {gameManager} from "../Game/GameManager"; import {TextField} from "../Components/TextField"; import Image = Phaser.GameObjects.Image; -import {GameSceneInitInterface} from "../Game/GameScene"; -import {StartMapInterface} from "../../Connexion/ConnexionModels"; import {mediaManager} from "../../WebRtc/MediaManager"; import {RESOLUTION} from "../../Enum/EnvironmentVariable"; import {SoundMeter} from "../Components/SoundMeter"; @@ -18,6 +16,8 @@ enum LoginTextures { arrowUp = "arrow_up" } +const helpCameraSettings = 'helpCameraSettings'; + export class EnableCameraScene extends Phaser.Scene { private textField!: TextField; private pressReturnField!: TextField; @@ -35,6 +35,8 @@ export class EnableCameraScene extends Phaser.Scene { private soundMeterSprite!: SoundMeterSprite; private microphoneNameField!: TextField; private repositionCallback!: (this: Window, ev: UIEvent) => void; + private helpCameraSettingsElement!: Phaser.GameObjects.DOMElement; + private helpCameraSettingsOpened: boolean = false; constructor() { super({ @@ -50,6 +52,7 @@ export class EnableCameraScene extends Phaser.Scene { 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'); + this.load.html(helpCameraSettings, 'resources/html/helpCameraSettings.html'); } create() { @@ -109,6 +112,27 @@ export class EnableCameraScene extends Phaser.Scene { this.soundMeterSprite.setVisible(false); this.add.existing(this.soundMeterSprite); + const middleX = (window.innerWidth / 3) - (370*0.85); + this.helpCameraSettingsElement = this.add.dom(middleX, -800, undefined, {overflow: 'scroll'}).createFromCache(helpCameraSettings); + this.revealMenusAfterInit(this.helpCameraSettingsElement, helpCameraSettings); + this.helpCameraSettingsElement.addListener('click'); + this.helpCameraSettingsElement.on('click', (event:MouseEvent) => { + event.preventDefault(); + if((event?.target as HTMLInputElement).id !== 'helpCameraSettingsFormRefresh') { + return; + } + const permission: Element = this.helpCameraSettingsElement.getChildByID('permissionError'); + permission.innerHTML = ''; + return mediaManager.getCamera().then(() => { + window.location.reload(); + }).catch((err) => { + permission.innerHTML = err.message; + }); + }); + if(this.helpCameraSettingsElement.parent){ + (this.helpCameraSettingsElement.parent as HTMLDivElement).style.overflow = 'scroll'; + } + this.repositionCallback = this.reposition.bind(this); window.addEventListener('resize', this.repositionCallback); } @@ -151,6 +175,9 @@ export class EnableCameraScene extends Phaser.Scene { * Function called each time a camera is changed */ private setupStream(stream: MediaStream): void { + if(this.helpCameraSettingsOpened){ + return; + } const img = HtmlUtils.getElementByIdOrFail('webRtcSetupNoVideo'); img.style.display = 'none'; @@ -257,19 +284,27 @@ export class EnableCameraScene extends Phaser.Scene { mediaManager.setLastUpdateScene(); } - private login(): void { - HtmlUtils.getElementByIdOrFail('webRtcSetup').style.display = 'none'; - this.soundMeter.stop(); - window.removeEventListener('resize', this.repositionCallback); - - mediaManager.stopCamera(); - mediaManager.stopMicrophone(); - - this.scene.sleep(EnableCameraSceneName) - gameManager.goToStartingMap(this.scene); + private login(): Promise { + return mediaManager.getCamera() + .then((mediaStream: MediaStream) => { + HtmlUtils.getElementByIdOrFail('webRtcSetup').style.display = 'none'; + this.soundMeter.stop(); + window.removeEventListener('resize', this.repositionCallback); + mediaManager.stopCamera(); + mediaManager.stopMicrophone(); + this.scene.sleep(EnableCameraSceneName) + gameManager.goToStartingMap(this.scene); + return mediaStream; + }).catch((err) => { + this.openHelpCameraSettingsOpened(); + throw err; + }); } private async getDevices() { + if(this.helpCameraSettingsOpened){ + return; + } const mediaDeviceInfos = await navigator.mediaDevices.enumerateDevices(); for (const mediaDeviceInfo of mediaDeviceInfos) { if (mediaDeviceInfo.kind === 'audioinput') { @@ -280,4 +315,47 @@ export class EnableCameraScene extends Phaser.Scene { } this.updateWebCamName(); } + + private openHelpCameraSettingsOpened(): void{ + this.reset(); + HtmlUtils.getElementByIdOrFail('webRtcSetup').style.display = 'none'; + this.helpCameraSettingsOpened = true; + let middleY = (window.innerHeight / 3) - (495); + if(middleY < 0){ + middleY = 0; + } + let middleX = (window.innerWidth / 3) - (370*0.85); + if(middleX < 0){ + middleX = 0; + } + this.tweens.add({ + targets: this.helpCameraSettingsElement, + y: middleY, + x: middleX, + duration: 1000, + ease: 'Power3', + overflow: 'scroll' + }); + } + + private revealMenusAfterInit(menuElement: Phaser.GameObjects.DOMElement, rootDomId: string) { + //Dom elements will appear inside the viewer screen when creating before being moved out of it, which create a flicker effect. + //To prevent this, we put a 'hidden' attribute on the root element, we remove it only after the init is done. + setTimeout(() => { + (menuElement.getChildByID(rootDomId) as HTMLElement).hidden = false; + }, 250); + } + + private reset(){ + this.textField.destroy(); + this.pressReturnField.destroy(); + this.cameraNameField.destroy(); + this.microphoneNameField.destroy(); + this.arrowRight.destroy(); + this.arrowLeft.destroy(); + this.arrowUp.destroy(); + this.arrowDown.destroy(); + this.soundMeterSprite.destroy(); + this.input.keyboard.removeAllKeys(); + } }