diff --git a/front/dist/resources/objects/layout_modes.png b/front/dist/resources/objects/layout_modes.png deleted file mode 100644 index abd9adaf..00000000 Binary files a/front/dist/resources/objects/layout_modes.png and /dev/null differ diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 30c4d8f8..9cb70020 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -43,7 +43,7 @@ import { TRIGGER_WEBSITE_PROPERTIES, WEBSITE_MESSAGE_PROPERTIES, AUDIO_VOLUME_PROPERTY, - AUDIO_LOOP_PROPERTY + AUDIO_LOOP_PROPERTY, Box } from "../../WebRtc/LayoutManager"; import {GameMap} from "./GameMap"; import {coWebsiteManager} from "../../WebRtc/CoWebsiteManager"; @@ -176,8 +176,6 @@ export class GameScene extends DirtyScene /*implements CenterListener*/ { y: -1000 } - private presentationModeSprite!: Sprite; - private chatModeSprite!: Sprite; private gameMap!: GameMap; private actionableItems: Map = new Map(); // The item that can be selected by pressing the space key. @@ -280,7 +278,6 @@ export class GameScene extends DirtyScene /*implements CenterListener*/ { this.onMapLoad(data); } - this.load.spritesheet('layout_modes', 'resources/objects/layout_modes.png', {frameWidth: 32, frameHeight: 32}); this.load.bitmapFont('main_font', 'resources/fonts/arcade.png', 'resources/fonts/arcade.xml'); //eslint-disable-next-line @typescript-eslint/no-explicit-any (this.load as any).rexWebFont({ @@ -502,10 +499,6 @@ export class GameScene extends DirtyScene /*implements CenterListener*/ { this.outlinedItem?.activate(); }); - this.presentationModeSprite = new PresentationModeIcon(this, 36, this.game.renderer.height - 2); - this.presentationModeSprite.on('pointerup', this.switchLayoutMode.bind(this)); - this.chatModeSprite = new ChatModeIcon(this, 70, this.game.renderer.height - 2); - this.chatModeSprite.on('pointerup', this.switchLayoutMode.bind(this)); this.openChatIcon = new OpenChatIcon(this, 2, this.game.renderer.height - 2) // FIXME: change this to use the UserInputManager class for input @@ -518,7 +511,7 @@ export class GameScene extends DirtyScene /*implements CenterListener*/ { // From now, this game scene will be notified of reposition events //layoutManager.setListener(this); - biggestAvailableArrayStore.subscribe((box) => this.updateCameraOffset()); + biggestAvailableArrayStore.subscribe((box) => this.updateCameraOffset(box)); this.triggerOnMapLayerPropertyChange(); this.listenToIframeEvents(); @@ -658,15 +651,11 @@ export class GameScene extends DirtyScene /*implements CenterListener*/ { const self = this; this.simplePeer.registerPeerConnectionListener({ onConnect(peer) { - self.presentationModeSprite.setVisible(true); - self.chatModeSprite.setVisible(true); self.openChatIcon.setVisible(true); audioManager.decreaseVolume(); }, onDisconnect(userId: number) { if (self.simplePeer.getNbConnections() === 0) { - self.presentationModeSprite.setVisible(false); - self.chatModeSprite.setVisible(false); self.openChatIcon.setVisible(false); audioManager.restoreVolume(); } @@ -1016,23 +1005,6 @@ ${escapedMessage} this.MapPlayersByKey = new Map(); } - private switchLayoutMode(): void { - //if discussion is activated, this layout cannot be activated - if(mediaManager.activatedDiscussion){ - return; - } - const mode = layoutManager.getLayoutMode(); - if (mode === LayoutMode.Presentation) { - layoutManager.switchLayoutMode(LayoutMode.VideoChat); - this.presentationModeSprite.setFrame(1); - this.chatModeSprite.setFrame(2); - } else { - layoutManager.switchLayoutMode(LayoutMode.Presentation); - this.presentationModeSprite.setFrame(0); - this.chatModeSprite.setFrame(3); - } - } - private initStartXAndStartY() { // If there is an init position passed if (this.initPosition !== null) { @@ -1523,8 +1495,6 @@ ${escapedMessage} } private reposition(): void { - this.presentationModeSprite.setY(this.game.renderer.height - 2); - this.chatModeSprite.setY(this.game.renderer.height - 2); this.openChatIcon.setY(this.game.renderer.height - 2); // Recompute camera offset if needed @@ -1536,8 +1506,7 @@ ${escapedMessage} * Updates the offset of the character compared to the center of the screen according to the layout manager * (tries to put the character in the center of the remaining space if there is a discussion going on. */ - private updateCameraOffset(): void { - const array = layoutManager.findBiggestAvailableArray(); + private updateCameraOffset(array: Box): void { const xCenter = (array.xEnd - array.xStart) / 2 + array.xStart; const yCenter = (array.yEnd - array.yStart) / 2 + array.yStart; diff --git a/front/src/WebRtc/LayoutManager.ts b/front/src/WebRtc/LayoutManager.ts index ad45f75d..5275a030 100644 --- a/front/src/WebRtc/LayoutManager.ts +++ b/front/src/WebRtc/LayoutManager.ts @@ -36,219 +36,10 @@ export const AUDIO_LOOP_PROPERTY = 'audioLoop'; export type Box = {xStart: number, yStart: number, xEnd: number, yEnd: number}; -/** - * This class is in charge of the video-conference layout. - * It receives positioning requests for videos and does its best to place them on the screen depending on the active layout mode. - */ class LayoutManager { - private mode: LayoutMode = LayoutMode.Presentation; - - private importantDivs: Map = new Map(); - private normalDivs: Map = new Map(); - private listener: CenterListener|null = null; - private actionButtonTrigger: Map = new Map(); private actionButtonInformation: Map = new Map(); - public setListener(centerListener: CenterListener|null) { - this.listener = centerListener; - } - - private positionDiv(elem: HTMLDivElement, importance: DivImportance): void { - if (this.mode === LayoutMode.VideoChat) { - const chatModeDiv = HtmlUtils.getElementByIdOrFail('chat-mode'); - chatModeDiv.appendChild(elem); - } else { - if (importance === DivImportance.Important) { - const mainSectionDiv = HtmlUtils.getElementByIdOrFail('main-section'); - mainSectionDiv.appendChild(elem); - } else if (importance === DivImportance.Normal) { - const sideBarDiv = HtmlUtils.getElementByIdOrFail('sidebar'); - sideBarDiv.appendChild(elem); - } - } - } - - /** - * Removes the DIV matching userId. - */ - public remove(userId: string): void { - console.log('Removing video for userID '+userId+'.'); - let div = this.importantDivs.get(userId); - if (div !== undefined) { - div.remove(); - this.importantDivs.delete(userId); - this.adjustVideoChatClass(); - this.listener?.onCenterChange(); - return; - } - - div = this.normalDivs.get(userId); - if (div !== undefined) { - div.remove(); - this.normalDivs.delete(userId); - this.adjustVideoChatClass(); - this.listener?.onCenterChange(); - return; - } - - console.log('Cannot remove userID '+userId+'. Already removed?'); - //throw new Error('Could not find user ID "'+userId+'"'); - } - - private adjustVideoChatClass(): void { - const chatModeDiv = HtmlUtils.getElementByIdOrFail('chat-mode'); - chatModeDiv.classList.remove('one-col', 'two-col', 'three-col', 'four-col'); - - const nbUsers = this.importantDivs.size + this.normalDivs.size; - - if (nbUsers <= 1) { - chatModeDiv.classList.add('one-col'); - } else if (nbUsers <= 4) { - chatModeDiv.classList.add('two-col'); - } else if (nbUsers <= 9) { - chatModeDiv.classList.add('three-col'); - } else { - chatModeDiv.classList.add('four-col'); - } - } - - public switchLayoutMode(layoutMode: LayoutMode) { - this.mode = layoutMode; - - if (layoutMode === LayoutMode.Presentation) { - HtmlUtils.getElementByIdOrFail('sidebar').style.display = 'flex'; - HtmlUtils.getElementByIdOrFail('main-section').style.display = 'flex'; - HtmlUtils.getElementByIdOrFail('chat-mode').style.display = 'none'; - } else { - HtmlUtils.getElementByIdOrFail('sidebar').style.display = 'none'; - HtmlUtils.getElementByIdOrFail('main-section').style.display = 'none'; - HtmlUtils.getElementByIdOrFail('chat-mode').style.display = 'grid'; - } - - for (const div of this.importantDivs.values()) { - this.positionDiv(div, DivImportance.Important); - } - for (const div of this.normalDivs.values()) { - this.positionDiv(div, DivImportance.Normal); - } - this.listener?.onCenterChange(); - } - - public getLayoutMode(): LayoutMode { - return this.mode; - } - - /*public getGameCenter(): {x: number, y: number} { - - }*/ - - /** - * Tries to find the biggest available box of remaining space (this is a space where we can center the character) - */ - public findBiggestAvailableArray(): Box { - const game = HtmlUtils.querySelectorOrFail('#game canvas'); - if (this.mode === LayoutMode.VideoChat) { - const children = document.querySelectorAll('div.chat-mode > div'); - const htmlChildren = Array.from(children.values()); - - // No chat? Let's go full center - if (htmlChildren.length === 0) { - return { - xStart: 0, - yStart: 0, - xEnd: game.offsetWidth, - yEnd: game.offsetHeight - } - } - - const lastDiv = htmlChildren[htmlChildren.length - 1]; - // Compute area between top right of the last div and bottom right of window - const area1 = (game.offsetWidth - (lastDiv.offsetLeft + lastDiv.offsetWidth)) - * (game.offsetHeight - lastDiv.offsetTop); - - // Compute area between bottom of last div and bottom of the screen on whole width - const area2 = game.offsetWidth - * (game.offsetHeight - (lastDiv.offsetTop + lastDiv.offsetHeight)); - - if (area1 < 0 && area2 < 0) { - // If screen is full, let's not attempt something foolish and simply center character in the middle. - return { - xStart: 0, - yStart: 0, - xEnd: game.offsetWidth, - yEnd: game.offsetHeight - } - } - if (area1 <= area2) { - console.log('lastDiv', lastDiv.offsetTop, lastDiv.offsetHeight); - return { - xStart: 0, - yStart: lastDiv.offsetTop + lastDiv.offsetHeight, - xEnd: game.offsetWidth, - yEnd: game.offsetHeight - } - } else { - console.log('lastDiv', lastDiv.offsetTop); - return { - xStart: lastDiv.offsetLeft + lastDiv.offsetWidth, - yStart: lastDiv.offsetTop, - xEnd: game.offsetWidth, - yEnd: game.offsetHeight - } - } - } else { - // Possible destinations: at the center bottom or at the right bottom. - const mainSectionChildren = Array.from(document.querySelectorAll('div.main-section > div').values()); - const sidebarChildren = Array.from(document.querySelectorAll('aside.sidebar > div').values()); - - // No presentation? Let's center on the screen - if (mainSectionChildren.length === 0) { - return { - xStart: 0, - yStart: 0, - xEnd: game.offsetWidth, - yEnd: game.offsetHeight - } - } - - // At this point, we know we have at least one element in the main section. - const lastPresentationDiv = mainSectionChildren[mainSectionChildren.length-1]; - - const presentationArea = (game.offsetHeight - (lastPresentationDiv.offsetTop + lastPresentationDiv.offsetHeight)) - * (lastPresentationDiv.offsetLeft + lastPresentationDiv.offsetWidth); - - let leftSideBar: number; - let bottomSideBar: number; - if (sidebarChildren.length === 0) { - leftSideBar = HtmlUtils.getElementByIdOrFail('sidebar').offsetLeft; - bottomSideBar = 0; - } else { - const lastSideBarChildren = sidebarChildren[sidebarChildren.length - 1]; - leftSideBar = lastSideBarChildren.offsetLeft; - bottomSideBar = lastSideBarChildren.offsetTop + lastSideBarChildren.offsetHeight; - } - const sideBarArea = (game.offsetWidth - leftSideBar) - * (game.offsetHeight - bottomSideBar); - - if (presentationArea <= sideBarArea) { - return { - xStart: leftSideBar, - yStart: bottomSideBar, - xEnd: game.offsetWidth, - yEnd: game.offsetHeight - } - } else { - return { - xStart: 0, - yStart: lastPresentationDiv.offsetTop + lastPresentationDiv.offsetHeight, - xEnd: /*lastPresentationDiv.offsetLeft + lastPresentationDiv.offsetWidth*/ game.offsetWidth , // To avoid flickering when a chat start, we center on the center of the screen, not the center of the main content area - yEnd: game.offsetHeight - } - } - } - } - public addActionButton(id: string, text: string, callBack: Function, userInputManager: UserInputManager){ //delete previous element this.removeActionButton(id, userInputManager);