From e06b20fe9683ad1634b7a59e32366ae4dae62c7c Mon Sep 17 00:00:00 2001 From: gparant Date: Fri, 1 May 2020 21:15:00 +0200 Subject: [PATCH] Update video style and start peer connexion --- back/src/Controller/IoSocketController.ts | 37 +++++---- back/src/Model/Group.ts | 23 ++++-- back/src/Model/World.ts | 10 +-- front/dist/index.html | 2 - front/dist/resources/style/style.css | 96 ++++++++-------------- front/src/Phaser/Player/Player.ts | 6 +- front/src/WebRtc/SimplePeer.ts | 97 +++++++++++++++-------- 7 files changed, 140 insertions(+), 131 deletions(-) diff --git a/back/src/Controller/IoSocketController.ts b/back/src/Controller/IoSocketController.ts index 23a238e6..3a17242a 100644 --- a/back/src/Controller/IoSocketController.ts +++ b/back/src/Controller/IoSocketController.ts @@ -8,7 +8,7 @@ import {SECRET_KEY} from "../Enum/EnvironmentVariable"; //TODO fix import by "_E import {ExtRooms, RefreshUserPositionFunction} from "../Model/Websocket/ExtRoom"; import {ExtRoomsInterface} from "../Model/Websocket/ExtRoomsInterface"; import {World} from "../Model/World"; -import { uuid } from 'uuidv4'; +import {Group} from "_Model/Group"; enum SockerIoEvent { CONNECTION = "connection", @@ -44,10 +44,10 @@ export class IoSocketController{ this.shareUsersPosition(); //don't send only function because the context will be not this - this.World = new World((user1 : string, user2 : string) => { - this.connectedUser(user1, user2); - }, (user1 : string, user2 : string) => { - this.disConnectedUser(user1, user2); + this.World = new World((user1 : string, user2 : string, group: Group) => { + this.connectedUser(user1, user2, group); + }, (user1 : string, user2 : string, group: Group) => { + this.disConnectedUser(user1, user2, group); }); } @@ -230,24 +230,27 @@ export class IoSocketController{ } //connected user - connectedUser(user1 : string, user2 : string){ - /* TODO manager room and group user to enter and leave */ - let roomId = uuid(); - let clients : Array = Object.values(this.Io.sockets.sockets); - let User1 = clients.find((user : ExSocketInterface) => user.userId === user1); - let User2 = clients.find((user : ExSocketInterface) => user.userId === user2); - - if(User1) { - this.joinWebRtcRoom(User1, roomId); + connectedUser(user1 : string, user2 : string, group : Group) { + if(!group){ + return; } - if(User2) { - this.joinWebRtcRoom(User2, roomId); + /* TODO manager room and group user to enter and leave */ + let clients: Array = Object.values(this.Io.sockets.sockets); + let User1 = clients.find((user: ExSocketInterface) => user.userId === user1); + let User2 = clients.find((user: ExSocketInterface) => user.userId === user2); + + if (User1) { + this.joinWebRtcRoom(User1, group.getId()); + } + if (User2) { + this.joinWebRtcRoom(User2, group.getId()); } } //connected user - disConnectedUser(user1 : string, user2 : string){ + disConnectedUser(user1 : string, user2 : string, group : Group){ console.log("disConnectedUser => user1", user1); console.log("disConnectedUser => user2", user2); + console.log("group", group); } } diff --git a/back/src/Model/Group.ts b/back/src/Model/Group.ts index 795c0e8e..099e871b 100644 --- a/back/src/Model/Group.ts +++ b/back/src/Model/Group.ts @@ -1,19 +1,25 @@ import {MessageUserPosition} from "./Websocket/MessageUserPosition"; import { World } from "./World"; import { UserInterface } from "./UserInterface"; +import {uuid} from "uuidv4"; export class Group { static readonly MAX_PER_GROUP = 4; + private id: string; private users: UserInterface[]; - private connectCallback: (user1: string, user2: string) => void; - private disconnectCallback: (user1: string, user2: string) => void; + private connectCallback: (user1: string, user2: string, group: Group) => void; + private disconnectCallback: (user1: string, user2: string, group: Group) => void; - constructor(users: UserInterface[], connectCallback: (user1: string, user2: string) => void, disconnectCallback: (user1: string, user2: string) => void) { + constructor(users: UserInterface[], + connectCallback: (user1: string, user2: string, group: Group) => void, + disconnectCallback: (user1: string, user2: string, group: Group) => void + ) { this.users = []; this.connectCallback = connectCallback; this.disconnectCallback = disconnectCallback; + this.id = uuid(); users.forEach((user: UserInterface) => { this.join(user); @@ -24,6 +30,10 @@ export class Group { return this.users; } + getId() : string{ + return this.id; + } + isFull(): boolean { return this.users.length >= Group.MAX_PER_GROUP; } @@ -31,9 +41,10 @@ export class Group { join(user: UserInterface): void { // Broadcast on the right event - this.users.forEach((groupUser: UserInterface) => { - this.connectCallback(user.id, groupUser.id); - }); + for(let i = 0; i < this.users.length; i++){ + let groupUser : UserInterface = this.users[i]; + this.connectCallback(user.id, groupUser.id, this); + } this.users.push(user); user.group = this; } diff --git a/back/src/Model/World.ts b/back/src/Model/World.ts index ff1f58ff..02391ec8 100644 --- a/back/src/Model/World.ts +++ b/back/src/Model/World.ts @@ -12,10 +12,10 @@ export class World { private users: Map; private groups: Group[]; - private connectCallback: (user1: string, user2: string) => void; - private disconnectCallback: (user1: string, user2: string) => void; + private connectCallback: (user1: string, user2: string, group: Group) => void; + private disconnectCallback: (user1: string, user2: string, group: Group) => void; - constructor(connectCallback: (user1: string, user2: string) => void, disconnectCallback: (user1: string, user2: string) => void) + constructor(connectCallback: (user1: string, user2: string, group: Group) => void, disconnectCallback: (user1: string, user2: string, group: Group) => void) { this.users = new Map(); this.groups = []; @@ -48,7 +48,6 @@ export class World { // If the user is not part of a group: // should he join a group? let closestUser: UserInterface|null = this.searchClosestAvailableUser(user); - if (closestUser !== null) { // Is the closest user part of a group? if (typeof closestUser.group === 'undefined') { @@ -60,9 +59,8 @@ export class World { closestUser.group.join(user); } } - } - // TODO : vérifier qu'ils ne sont pas déja dans un groupe plein + // TODO : vérifier qu'ils ne sont pas déja dans un groupe plein } /** diff --git a/front/dist/index.html b/front/dist/index.html index a9f51d4d..c1b3eb52 100644 --- a/front/dist/index.html +++ b/front/dist/index.html @@ -12,8 +12,6 @@
-
-
diff --git a/front/dist/resources/style/style.css b/front/dist/resources/style/style.css index 9e2d2daa..58965b2e 100644 --- a/front/dist/resources/style/style.css +++ b/front/dist/resources/style/style.css @@ -1,77 +1,44 @@ .webrtc{ display: none; + position: absolute; + right: 0px; + height: 100%; + width: 300px; } .webrtc.active{ display: block; } -.webrtc, .activeCam{ - position: absolute; - left: 0; - top: 0; - width: 100%; - height: 100%; - background: black; -} +.webrtc, .activeCam{} .activeCam video{ position: absolute; - width: 100%; - height: 100%; + width: 300px; + height: 20%; + top: 10px; + right: 10px; + margin: 5px; + background-color: white; +} +.activeCam video#myCamVideo{ + width: 200px; + height: 100px; } /*CSS size for 2 - 3 elements*/ -video:nth-child(1):nth-last-child(3), -video:nth-child(2):nth-last-child(2), -video:nth-child(3):nth-last-child(1), -video:nth-child(1):nth-last-child(2), -video:nth-child(2):nth-last-child(1){ - width: 50%; +.activeCam video:nth-child(1){ + /*this is for camera of user*/ + top: 75%; } -video:nth-child(1):nth-last-child(3), -video:nth-child(2):nth-last-child(2), -video:nth-child(3):nth-last-child(1){ - height: 50%; +.activeCam video:nth-child(2){ + top: 0%; } - -/*CSS position for 2 elements*/ -video:nth-child(1):nth-last-child(2){ - left: 0; +.activeCam video:nth-child(3){ + top: 25%; } -video:nth-child(2):nth-last-child(1){ - left: 50%; -} - -/*CSS position for 3 elements*/ -video:nth-child(1):nth-last-child(3){ - top: 0; - left: 0; -} -video:nth-child(2):nth-last-child(2){ - top: 0; - left: 50%; -} -video:nth-child(3):nth-last-child(1) { +.activeCam video:nth-child(4) { top: 50%; - left: 25%; } -.myCam{ - height: 200px; - width: 300px; - position: absolute; - right: 10px; - background: black; - border: none; - bottom: 20px; - max-height: 17%; - max-width: 17%; - opacity: 1; - display: block; - transition: opacity 1s; -} -.myCam video{ - width: 100%; - height: 100%; -} +/*btn animation*/ .btn-cam-action div{ cursor: pointer; position: absolute; @@ -79,14 +46,14 @@ video:nth-child(3):nth-last-child(1) { width: 64px; height: 64px; background: #666; - left: 6vw; box-shadow: 2px 2px 24px #444; border-radius: 48px; - transform: translateX(calc(-6vw - 96px)); + transform: translateY(12vw); transition-timing-function: ease-in-out; + bottom: 20px; } .webrtc:hover .btn-cam-action.active div{ - transform: translateX(0); + transform: translateY(0); } .btn-cam-action div:hover{ background: #407cf7; @@ -94,16 +61,16 @@ video:nth-child(3):nth-last-child(1) { transition: 280ms; } .btn-micro{ - bottom: 277px; transition: all .3s; + left: 168px; } .btn-video{ - bottom: 177px; transition: all .2s; + left: 84px; } .btn-call{ - bottom: 77px; transition: all .1s; + left: 0px; } .btn-cam-action div img{ height: 32px; @@ -112,6 +79,8 @@ video:nth-child(3):nth-last-child(1) { left: calc(48px - 35px); position: relative; } + +/*Phone Animation*/ .phone-open{ position: absolute; border-radius: 50%; @@ -136,7 +105,6 @@ video:nth-child(3):nth-last-child(1) { animation: none; cursor: pointer; } - @keyframes phone-move { 0% { left: calc(50% - 70px); diff --git a/front/src/Phaser/Player/Player.ts b/front/src/Phaser/Player/Player.ts index a7798720..7eaf4dfb 100644 --- a/front/src/Phaser/Player/Player.ts +++ b/front/src/Phaser/Player/Player.ts @@ -25,6 +25,7 @@ export class Player extends PlayableCaracter implements CurrentGamerInterface, G userId: string; PlayerValue: string; userInputManager: UserInputManager; + previousMove: string; constructor( userId: string, @@ -90,7 +91,10 @@ export class Player extends PlayableCaracter implements CurrentGamerInterface, G direction = PlayerAnimationNames.None; this.stop(); } - this.sharePosition(direction); + if(this.previousMove !== PlayerAnimationNames.None || direction !== PlayerAnimationNames.None){ + this.sharePosition(direction); + } + this.previousMove = direction; } private sharePosition(direction: string) { diff --git a/front/src/WebRtc/SimplePeer.ts b/front/src/WebRtc/SimplePeer.ts index 3c94bbaf..60a2c5a9 100644 --- a/front/src/WebRtc/SimplePeer.ts +++ b/front/src/WebRtc/SimplePeer.ts @@ -4,14 +4,19 @@ let Peer = require('simple-peer'); export interface SimplePeerInterface { } - +enum PeerConnexionStatus{ + DISABLED = 1, + ACTIVATED = 2 +} export class SimplePeer { - Connexion: ConnexionInterface; - MediaManager: MediaManager; - WebRtcRoomId: string; - Users: Array; + private Connexion: ConnexionInterface; + private MediaManager: MediaManager; + private WebRtcRoomId: string; + private Users: Array; - PeerConnexionArray: Array = new Array(); + private PeerConnexionArray: Array = new Array(); + + private PeerConnexionStatus : number = PeerConnexionStatus.DISABLED; constructor(Connexion: ConnexionInterface, WebRtcRoomId: string = "test-webrtc") { this.Connexion = Connexion; @@ -31,55 +36,71 @@ export class SimplePeer { }); //when button to call is clicked, start video - this.MediaManager.getElementActivePhone().addEventListener("click", () => { + /*this.MediaManager.getElementActivePhone().addEventListener("click", () => { this.startWebRtc(); this.disablePhone(); + });*/ + + return this.MediaManager.getCamera().then((stream: MediaStream) => { + this.MediaManager.activeVisio(); + this.MediaManager.localStream = stream; }); } /** * server has two person connected, start the meet */ - startWebRtc() { - this.MediaManager.activeVisio(); - return this.MediaManager.getCamera().then((stream: MediaStream) => { - this.MediaManager.localStream = stream; + private startWebRtc() { + //create pear connexion + this.createPeerConnexion(); - //create pear connexion - this.createPeerConnexion(); - - //receive signal by gemer - this.Connexion.receiveWebrtcSignal((message: string) => { - this.receiveWebrtcSignal(message); - }); - }).catch((err) => { - console.error(err); + //receive signal by gemer + this.Connexion.receiveWebrtcSignal((message: string) => { + this.receiveWebrtcSignal(message); }); + + // add media or new media for all peer connexion + this.Users.forEach((user: any) => { + this.addMedia(user.userId); + }); + + //change status to manage other user + this.PeerConnexionStatus = PeerConnexionStatus.ACTIVATED; } /** * * @param message */ - receiveWebrtcStart(message: string) { + private receiveWebrtcStart(message: string) { let data = JSON.parse(message); this.WebRtcRoomId = data.roomId; this.Users = data.clients; - //active button for player - this.activePhone(); + console.log("receiveWebrtcStart", this.Users); + + //start connexion + this.startWebRtc(); } - createPeerConnexion() { + private createPeerConnexion() { this.Users.forEach((user: any) => { - if(this.PeerConnexionArray[user.userId]){ + if (this.PeerConnexionArray[user.userId]) { return; } this.MediaManager.addActiveVideo(user.userId); - this.PeerConnexionArray[user.userId] = new Peer({initiator: user.initiator}); + console.info("createPeerConnexion => create peerConexion", user); + this.PeerConnexionArray[user.userId] = new Peer({ + initiator: user.initiator, + config: { iceServers: [{ urls: 'stun:stun.l.google.com:19302' }, { urls: 'stun:global.stun.twilio.com:3478?transport=udp' }] } + }); + + //add lof info PeerConnexionArray + this.PeerConnexionArray[user.userId]._debug = console.info; this.PeerConnexionArray[user.userId].on('signal', (data: any) => { + console.info("createPeerConnexion => sendWebrtcSignal : "+user.userId, data); this.sendWebrtcSignal(data, user.userId); }); @@ -88,15 +109,15 @@ export class SimplePeer { }); this.PeerConnexionArray[user.userId].on('close', () => { + console.info("createPeerConnexion => close", user.userId); this.closeConnexion(user.userId); }); this.addMedia(user.userId); }); - } - closeConnexion(userId : string){ + private closeConnexion(userId : string){ // @ts-ignore this.PeerConnexionArray[userId] = null; this.MediaManager.removeActiveVideo(userId) @@ -107,7 +128,7 @@ export class SimplePeer { * @param userId * @param data */ - sendWebrtcSignal(data: any, userId : string) { + private sendWebrtcSignal(data: any, userId : string) { this.Connexion.sendWebrtcSignal(data, this.WebRtcRoomId, null, userId); } @@ -115,8 +136,10 @@ export class SimplePeer { * * @param message */ - receiveWebrtcSignal(message: string) { + private receiveWebrtcSignal(message: string) { let data = JSON.parse(message); + console.log("receiveWebrtcSignal", data); + console.log("this.PeerConnexionArray[data.userId]", this.PeerConnexionArray[data.userId]); if(!this.PeerConnexionArray[data.userId]){ return; } @@ -128,7 +151,7 @@ export class SimplePeer { * @param userId * @param stream */ - stream(userId : any, stream: MediaStream) { + private stream(userId : any, stream: MediaStream) { this.MediaManager.remoteVideo[userId].srcObject = stream; } @@ -136,15 +159,19 @@ export class SimplePeer { * * @param userId */ - addMedia (userId : any) { - this.PeerConnexionArray[userId].addStream(this.MediaManager.localStream) // <- add streams to peer dynamically + private addMedia (userId : any = null) { + if (!this.MediaManager.localStream || !this.PeerConnexionArray[userId]) { + return; + } + this.PeerConnexionArray[userId].addStream(this.MediaManager.localStream) // <- add streams to peer dynamically + return; } - activePhone(){ + private activePhone(){ this.MediaManager.activePhoneOpen(); } - disablePhone(){ + private disablePhone(){ this.MediaManager.disablePhoneOpen(); } } \ No newline at end of file