diff --git a/front/src/Components/VisitCard/VisitCard.svelte b/front/src/Components/VisitCard/VisitCard.svelte index 5cdb4cfe..ebf22934 100644 --- a/front/src/Components/VisitCard/VisitCard.svelte +++ b/front/src/Components/VisitCard/VisitCard.svelte @@ -2,24 +2,24 @@ import { fly } from 'svelte/transition'; import {requestVisitCardsStore} from "../../Stores/GameStore"; import {onMount} from "svelte"; - + export let visitCardUrl: string; let w = '500px'; let h = '250px'; let hidden = true; let cvIframe; - + function closeCard() { requestVisitCardsStore.set(null); } - + function handleIframeMessage(message:any) { if (message.data.type === 'cvIframeSize') { w = (message.data.data.w) + 'px'; h = (message.data.data.h) + 'px'; } } - + onMount(() => { cvIframe.onload = () => hidden = false cvIframe.onerror = () => hidden = false @@ -42,7 +42,7 @@ 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } - + .visitCard { pointer-events: all; margin-left: auto; @@ -54,7 +54,7 @@ border: 0; max-width: 80vw; overflow: hidden; - + &.hidden { visibility: hidden; position: absolute; @@ -78,7 +78,7 @@ {/if} - + diff --git a/front/src/Phaser/Login/CustomizeScene.ts b/front/src/Phaser/Login/CustomizeScene.ts index f1d48235..9d0e7877 100644 --- a/front/src/Phaser/Login/CustomizeScene.ts +++ b/front/src/Phaser/Login/CustomizeScene.ts @@ -2,26 +2,20 @@ import {EnableCameraSceneName} from "./EnableCameraScene"; import Rectangle = Phaser.GameObjects.Rectangle; import {loadAllLayers} from "../Entity/PlayerTexturesLoadingManager"; import Sprite = Phaser.GameObjects.Sprite; -import Container = Phaser.GameObjects.Container; import {gameManager} from "../Game/GameManager"; import {localUserStore} from "../../Connexion/LocalUserStore"; import {addLoader} from "../Components/Loader"; import type {BodyResourceDescriptionInterface} from "../Entity/PlayerTextures"; import {AbstractCharacterScene} from "./AbstractCharacterScene"; import {areCharacterLayersValid} from "../../Connexion/LocalUser"; -import { MenuScene } from "../Menu/MenuScene"; import { SelectCharacterSceneName } from "./SelectCharacterScene"; import {customCharacterSceneVisibleStore} from "../../Stores/CustomCharacterStore"; -import {selectCharacterSceneVisibleStore} from "../../Stores/SelectCharacterStore"; import {waScaleManager} from "../Services/WaScaleManager"; import {isMobile} from "../../Enum/EnvironmentVariable"; import {CustomizedCharacter} from "../Entity/CustomizedCharacter"; export const CustomizeSceneName = "CustomizeScene"; -export const CustomizeSceneKey = "CustomizeScene"; -const customizeSceneKey = 'customizeScene'; - export class CustomizeScene extends AbstractCharacterScene { private Rectangle!: Rectangle; @@ -42,7 +36,6 @@ export class CustomizeScene extends AbstractCharacterScene { } preload() { - this.load.html(customizeSceneKey, 'resources/html/CustomCharacterScene.html'); this.loadCustomSceneSelectCharacters().then((bodyResourceDescriptions) => { bodyResourceDescriptions.forEach((bodyResourceDescription) => { @@ -111,7 +104,15 @@ export class CustomizeScene extends AbstractCharacterScene { this.onResize(); } - public doMoveCursorHorizontally(index: number): void { + public moveCursorHorizontally(index: number): void { + this.moveHorizontally = index; + } + + public moveCursorVertically(index: number): void { + this.moveVertically = index; + } + + private doMoveCursorHorizontally(index: number): void { this.selectedLayers[this.activeRow] += index; if (this.selectedLayers[this.activeRow] < 0) { this.selectedLayers[this.activeRow] = 0 @@ -123,7 +124,7 @@ export class CustomizeScene extends AbstractCharacterScene { this.saveInLocalStorage(); } - public doMoveCursorVertically(index:number): void { + private doMoveCursorVertically(index:number): void { this.activeRow += index; if (this.activeRow < 0) { diff --git a/front/src/Phaser/Login/SelectCharacterScene.ts b/front/src/Phaser/Login/SelectCharacterScene.ts index 0d01bd88..1abd58e5 100644 --- a/front/src/Phaser/Login/SelectCharacterScene.ts +++ b/front/src/Phaser/Login/SelectCharacterScene.ts @@ -10,17 +10,13 @@ import {AbstractCharacterScene} from "./AbstractCharacterScene"; import {areCharacterLayersValid} from "../../Connexion/LocalUser"; import {touchScreenManager} from "../../Touch/TouchScreenManager"; import {PinchManager} from "../UserInput/PinchManager"; -import {MenuScene} from "../Menu/MenuScene"; import {selectCharacterSceneVisibleStore} from "../../Stores/SelectCharacterStore"; -import {customCharacterSceneVisibleStore} from "../../Stores/CustomCharacterStore"; import {waScaleManager} from "../Services/WaScaleManager"; import {isMobile} from "../../Enum/EnvironmentVariable"; //todo: put this constants in a dedicated file export const SelectCharacterSceneName = "SelectCharacterScene"; -const selectCharacterKey = 'selectCharacterScene'; - export class SelectCharacterScene extends AbstractCharacterScene { protected readonly nbCharactersPerRow = 6; protected selectedPlayer!: Phaser.Physics.Arcade.Sprite|null; // null if we are selecting the "customize" option @@ -29,7 +25,6 @@ export class SelectCharacterScene extends AbstractCharacterScene { protected selectedRectangle!: Rectangle; - protected selectCharacterSceneElement!: Phaser.GameObjects.DOMElement; protected currentSelectUser = 0; protected pointerClicked: boolean = false; protected pointerTimer: number = 0; @@ -43,7 +38,6 @@ export class SelectCharacterScene extends AbstractCharacterScene { } preload() { - this.load.html(selectCharacterKey, 'resources/html/selectCharacterScene.html'); this.loadSelectSceneCharacters().then((bodyResourceDescriptions) => { bodyResourceDescriptions.forEach((bodyResourceDescription) => { diff --git a/front/src/Phaser/Services/WaScaleManager.ts b/front/src/Phaser/Services/WaScaleManager.ts index 1da0fcf3..abfd2a8b 100644 --- a/front/src/Phaser/Services/WaScaleManager.ts +++ b/front/src/Phaser/Services/WaScaleManager.ts @@ -3,6 +3,7 @@ import ScaleManager = Phaser.Scale.ScaleManager; import {coWebsiteManager} from "../../WebRtc/CoWebsiteManager"; import type {Game} from "../Game/Game"; import {ResizableScene} from "../Login/ResizableScene"; +import {HtmlUtils} from "../../WebRtc/HtmlUtils"; class WaScaleManager { @@ -39,6 +40,12 @@ class WaScaleManager { const style = this.scaleManager.canvas.style; style.width = Math.ceil(realSize.width / devicePixelRatio) + 'px'; style.height = Math.ceil(realSize.height / devicePixelRatio) + 'px'; + + // Resize the game element at the same size at the canvas + const gameStyle = HtmlUtils.getElementByIdOrFail('game').style; + gameStyle.width = style.width; + gameStyle.height = style.height; + // Note: onResize will be called twice (once here and once in Game.ts), but we have no better way. for (const scene of this.game.scene.getScenes(true)) { if (scene instanceof ResizableScene) { diff --git a/front/src/WebRtc/CoWebsiteManager.ts b/front/src/WebRtc/CoWebsiteManager.ts index 9793cd25..1fb28487 100644 --- a/front/src/WebRtc/CoWebsiteManager.ts +++ b/front/src/WebRtc/CoWebsiteManager.ts @@ -1,6 +1,7 @@ import {HtmlUtils} from "./HtmlUtils"; import {Subject} from "rxjs"; import {iframeListener} from "../Api/IframeListener"; +import {touchScreenManager} from "../Touch/TouchScreenManager"; enum iframeStates { closed = 1, @@ -17,6 +18,11 @@ const cowebsiteOpenFullScreenImageId = 'cowebsite-fullscreen-open'; const cowebsiteCloseFullScreenImageId = 'cowebsite-fullscreen-close'; const animationTime = 500; //time used by the css transitions, in ms. +interface TouchMoveCoordinates { + x: number; + y: number; +} + class CoWebsiteManager { private opened: iframeStates = iframeStates.closed; @@ -32,6 +38,7 @@ class CoWebsiteManager { private resizing: boolean = false; private cowebsiteMainDom: HTMLDivElement; private cowebsiteAsideDom: HTMLDivElement; + private previousTouchMoveCoordinates: TouchMoveCoordinates|null = null; //only use on touchscreens to track touch movement get width(): number { return this.cowebsiteDiv.clientWidth; @@ -62,7 +69,10 @@ class CoWebsiteManager { this.cowebsiteMainDom = HtmlUtils.getElementByIdOrFail(cowebsiteMainDomId); this.cowebsiteAsideDom = HtmlUtils.getElementByIdOrFail(cowebsiteAsideDomId); - this.initResizeListeners(); + if (touchScreenManager.supportTouchScreen) { + this.initResizeListeners(true); + } + this.initResizeListeners(false); const buttonCloseFrame = HtmlUtils.getElementByIdOrFail(cowebsiteCloseButtonId); buttonCloseFrame.addEventListener('click', () => { @@ -77,22 +87,43 @@ class CoWebsiteManager { }); } - private initResizeListeners() { - const movecallback = (event:MouseEvent) => { - this.verticalMode ? this.height += event.movementY / this.getDevicePixelRatio() : this.width -= event.movementX / this.getDevicePixelRatio(); + private initResizeListeners(touchMode:boolean) { + const movecallback = (event:MouseEvent|TouchEvent) => { + let x, y; + if (event.type === 'mousemove') { + x = (event as MouseEvent).movementX / this.getDevicePixelRatio(); + y = (event as MouseEvent).movementY / this.getDevicePixelRatio(); + } else { + const touchEvent = (event as TouchEvent).touches[0]; + const last = {x: touchEvent.pageX, y: touchEvent.pageY}; + const previous = this.previousTouchMoveCoordinates as TouchMoveCoordinates; + this.previousTouchMoveCoordinates = last; + x = last.x - previous.x; + y = last.y - previous.y; + } + + + this.verticalMode ? this.height += y : this.width -= x; this.fire(); } - this.cowebsiteAsideDom.addEventListener('mousedown', (event) => { + this.cowebsiteAsideDom.addEventListener( touchMode ? 'touchstart' : 'mousedown', (event) => { this.resizing = true; this.getIframeDom().style.display = 'none'; + if (touchMode) { + const touchEvent = (event as TouchEvent).touches[0]; + this.previousTouchMoveCoordinates = {x: touchEvent.pageX, y: touchEvent.pageY}; + } - document.addEventListener('mousemove', movecallback); + document.addEventListener(touchMode ? 'touchmove' : 'mousemove', movecallback); }); - document.addEventListener('mouseup', (event) => { + document.addEventListener(touchMode ? 'touchend' : 'mouseup', (event) => { if (!this.resizing) return; - document.removeEventListener('mousemove', movecallback); + if (touchMode) { + this.previousTouchMoveCoordinates = null; + } + document.removeEventListener(touchMode ? 'touchmove' : 'mousemove', movecallback); this.getIframeDom().style.display = 'block'; this.resizing = false; }); diff --git a/front/style/cowebsite-mobile.scss b/front/style/cowebsite-mobile.scss index 85b41511..48a6689e 100644 --- a/front/style/cowebsite-mobile.scss +++ b/front/style/cowebsite-mobile.scss @@ -28,6 +28,7 @@ aside { height: 30px; + min-height: 30px; cursor: ns-resize; flex-direction: column; diff --git a/front/style/cowebsite.scss b/front/style/cowebsite.scss index 2ed1ef69..e508b58d 100644 --- a/front/style/cowebsite.scss +++ b/front/style/cowebsite.scss @@ -13,6 +13,8 @@ iframe { width: 100%; height: 100%; + max-width: 100vw; + max-height: 100vh; } } diff --git a/front/style/style.scss b/front/style/style.scss index 8522d4a4..beed1db5 100644 --- a/front/style/style.scss +++ b/front/style/style.scss @@ -337,12 +337,12 @@ video.myCamVideo{ /* New layout */ body { margin: 0; - height: 100vh; - width: 100vw; + height: 100%; + width: 100%; } .main-container { - height: 100vh; - width: 100vw; + height: 100%; + width: 100%; position: absolute; } @@ -367,8 +367,6 @@ body { } #game { - height: 100%; - width: 100%; position: relative; /* Position relative is needed for the game-overlay. */ } @@ -589,7 +587,6 @@ input[type=range]:focus::-ms-fill-upper { /* Let's make sure videos are vertically centered if they need to be cropped */ .media-container { display: flex; - justify-content: center; flex-direction: column; overflow: hidden; border-radius: 15px;