Merge pull request #990 from thecodingmachine/develop

Release 04/05

- WorkAdventure Village
- Fix loader
- Create sound meter
This commit is contained in:
grégoire parant 2021-05-05 02:05:07 +02:00 committed by GitHub
commit 4d0220e118
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
51 changed files with 624 additions and 181 deletions

View File

@ -48,20 +48,27 @@
<div id="activeCam" class="activeCam"> <div id="activeCam" class="activeCam">
<div id="div-myCamVideo" class="video-container"> <div id="div-myCamVideo" class="video-container">
<video id="myCamVideo" autoplay muted></video> <video id="myCamVideo" autoplay muted></video>
<div id="mySoundMeter" class="sound-progress">
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
</div> </div>
</div> </div>
<div class="btn-cam-action"> <div class="btn-cam-action">
<div id="btn-micro" class="btn-micro"> <div id="btn-monitor" class="btn-monitor">
<img id="microphone" src="resources/logos/microphone.svg"> <img id="monitor" src="resources/logos/monitor.svg">
<img id="microphone-close" src="resources/logos/microphone-close.svg"> <img id="monitor-close" src="resources/logos/monitor-close.svg">
</div> </div>
<div id="btn-video" class="btn-video"> <div id="btn-video" class="btn-video">
<img id="cinema" src="resources/logos/cinema.svg"> <img id="cinema" src="resources/logos/cinema.svg">
<img id="cinema-close" src="resources/logos/cinema-close.svg"> <img id="cinema-close" src="resources/logos/cinema-close.svg">
</div> </div>
<div id="btn-monitor" class="btn-monitor"> <div id="btn-micro" class="btn-micro">
<img id="monitor" src="resources/logos/monitor.svg"> <img id="microphone" src="resources/logos/microphone.svg">
<img id="monitor-close" src="resources/logos/monitor-close.svg"> <img id="microphone-close" src="resources/logos/microphone-close.svg">
</div> </div>
</div> </div>

View File

@ -48,7 +48,7 @@
text-align: center; text-align: center;
margin: 0; margin: 0;
position: absolute; position: absolute;
top: 44vh; top: 40vh;
width: 100%; width: 100%;
} }
#enableCameraScene button { #enableCameraScene button {

View File

@ -60,6 +60,9 @@
font-size: 8px; font-size: 8px;
margin: 0px 20px; margin: 0px 20px;
} }
#helpCameraSettings section p a{
font-size: 8px;
}
#helpCameraSettings section p.err{ #helpCameraSettings section p.err{
color: #ff0000; color: #ff0000;
} }
@ -95,6 +98,10 @@
<p>If you prefer to continue without allowing camera and microphone access, click on Continue</p> <p>If you prefer to continue without allowing camera and microphone access, click on Continue</p>
<p id='browserHelpSetting'></p> <p id='browserHelpSetting'></p>
</section> </section>
<!--<section class="text-center">
<p>If your problem persist, please contact us: <a id="mailto" href="mailto:workadventure@thecodingmachine.com?subject=Support camera and microphone settings" target="_blank"> workadventure@thecodingmachine.com</a>.</p>
</section>-->
</section>
<section class="action"> <section class="action">
<a href="#" id="helpCameraSettingsFormRefresh">Refresh</a> <a href="#" id="helpCameraSettingsFormRefresh">Refresh</a>
<button type="submit" id="helpCameraSettingsFormContinue">Continue</button> <button type="submit" id="helpCameraSettingsFormContinue">Continue</button>

View File

@ -23,27 +23,17 @@
} }
.btn-cam-action { .btn-cam-action {
min-width: 150px;
&:hover{ &:hover{
transform: translateY(20px); transform: translateY(20px);
} }
div { div {
margin: 0 1%;
&:hover { &:hover {
background-color: #666; background-color: #666;
} }
margin-bottom: 30px;
bottom: 30px;
&.btn-micro {
right: 0;
}
&.btn-monitor {
right: 130px;
}
&.btn-video {
right: 65px;
}
} }
} }

View File

@ -98,7 +98,7 @@ body .message-info.warning{
} }
.video-container button.report:hover { .video-container button.report:hover {
width: 150px; width: 160px;
} }
.video-container button.report img{ .video-container button.report img{
@ -126,6 +126,7 @@ body .message-info.warning{
.video-container video{ .video-container video{
height: 100%; height: 100%;
cursor: url('/resources/logos/cursor_pointer.png'), pointer;
} }
.video-container video:focus{ .video-container video:focus{
@ -141,7 +142,7 @@ body .message-info.warning{
right: 15px; right: 15px;
bottom: 30px; bottom: 30px;
border-radius: 15px 15px 15px 15px; border-radius: 15px 15px 15px 15px;
max-height: 200px; max-height: 20%;
} }
video#myCamVideo{ video#myCamVideo{
@ -153,19 +154,60 @@ video#myCamVideo{
/*height: 113px;*/ /*height: 113px;*/
} }
.sound-progress{
display: none;
position: absolute;
right: 14px;
top: calc(50% - 5px);
}
.sound-progress.active{
display: table-column;
}
.sound-progress span{
position: absolute;
color: black;
background-color: #00000020;
width: 5px;
height: 5px;
border-radius: 50%;
}
.sound-progress span.active{
background-color: #00c3ff66
}
.sound-progress span:nth-child(1){
top: calc(50% + 20px);
}
.sound-progress span:nth-child(2){
top: calc(50% + 10px);
}
.sound-progress span:nth-child(3){
top: calc(50% - 0px);
}
.sound-progress span:nth-child(4){
top: calc(50% - 10px);
}
.sound-progress span:nth-child(5){
top: calc(50% - 20px);
}
.btn-cam-action { .btn-cam-action {
pointer-events: all; pointer-events: all;
position: absolute; position: absolute;
bottom: 0px; display: inline-flex;
right: 0px; bottom: 10px;
width: 450px; right: 15px;
height: 150px; width: 15vw;
height: 40px;
text-align: center;
align-content: center;
align-items: center;
justify-content: center;
justify-items: center;
} }
/*btn animation*/ /*btn animation*/
.btn-cam-action div{ .btn-cam-action div{
cursor: url('/resources/logos/cursor_pointer.png'), pointer; cursor: url('/resources/logos/cursor_pointer.png'), pointer;
position: absolute; /*position: absolute;*/
border: solid 0px black; border: solid 0px black;
width: 44px; width: 44px;
height: 44px; height: 44px;
@ -174,7 +216,8 @@ video#myCamVideo{
border-radius: 48px; border-radius: 48px;
transform: translateY(20px); transform: translateY(20px);
transition-timing-function: ease-in-out; transition-timing-function: ease-in-out;
bottom: 20px; margin-bottom: 20px;
margin: 0 4%;
} }
.btn-cam-action div.disabled { .btn-cam-action div.disabled {
background: #d75555; background: #d75555;
@ -193,17 +236,17 @@ video#myCamVideo{
.btn-micro{ .btn-micro{
pointer-events: auto; pointer-events: auto;
transition: all .3s; transition: all .3s;
right: 44px; /*right: 44px;*/
} }
.btn-video{ .btn-video{
pointer-events: auto; pointer-events: auto;
transition: all .25s; transition: all .25s;
right: 134px; /*right: 134px;*/
} }
.btn-monitor{ .btn-monitor{
pointer-events: auto; pointer-events: auto;
transition: all .2s; transition: all .2s;
right: 224px; /*right: 224px;*/
} }
.btn-copy{ .btn-copy{
pointer-events: auto; pointer-events: auto;
@ -497,7 +540,7 @@ input[type=range]:focus::-ms-fill-upper {
position: absolute; position: absolute;
width: 100%; width: 100%;
height: 100%; height: 100%;
pointer-events: none; pointer-events: all;
/* TODO: DO WE NEED FLEX HERE???? WE WANT A SIDEBAR OF EXACTLY 25% (note: flex useful for direction!!!) */ /* TODO: DO WE NEED FLEX HERE???? WE WANT A SIDEBAR OF EXACTLY 25% (note: flex useful for direction!!!) */
} }
@ -533,7 +576,7 @@ input[type=range]:focus::-ms-fill-upper {
.sidebar { .sidebar {
flex: 0 0 25%; flex: 0 0 25%;
display: flex; display: flex;
pointer-events: none; pointer-events: all;
} }
.sidebar > div { .sidebar > div {
@ -547,6 +590,10 @@ input[type=range]:focus::-ms-fill-upper {
margin: 0%; margin: 0%;
} }
.sidebar > div video {
cursor: url('/resources/logos/cursor_pointer.png'), pointer;
}
/* Let's make sure videos are vertically centered if they need to be cropped */ /* Let's make sure videos are vertically centered if they need to be cropped */
.media-container { .media-container {
display: flex; display: flex;
@ -1111,17 +1158,34 @@ div.action{
animation-iteration-count: infinite; animation-iteration-count: infinite;
animation-timing-function: ease-in-out; animation-timing-function: ease-in-out;
} }
div.action.info,
div.action.warning,
div.action.danger{
transition: all 1s ease;
animation: mymove 1s;
animation-iteration-count: infinite;
animation-timing-function: ease-in-out;
}
div.action p.action-body{ div.action p.action-body{
cursor: url('/resources/logos/cursor_pointer.png'), pointer;
padding: 10px; padding: 10px;
background-color: #2d2d2dba; background-color: #2d2d2dba;
color: #fff; color: #fff;
font-size: 14px; font-size: 14px;
font-weight: 500; font-weight: 500;
text-align: center; text-align: center;
max-width: 250px; max-width: 350px;
margin-left: calc(50% - 125px); margin-left: calc(50% - 175px);
border-radius: 15px; border-radius: 15px;
} }
div.action.warning p.action-body{
background-color: #ff9800eb;
color: #000;
}
div.action.danger p.action-body{
background-color: #da0000e3;
color: #000;
}
.popUpElement{ .popUpElement{
font-family: 'Press Start 2P'; font-family: 'Press Start 2P';
text-align: left; text-align: left;

View File

@ -1,41 +1,149 @@
{ {
"name": "App", "short_name": "WA",
"icons": [ "name": "WorkAdventure",
{ "icons": [
"src": "\/android-icon-36x36.png", {
"sizes": "36x36", "src": "/static/images/favicons/apple-icon-57x57.png",
"type": "image\/png", "sizes": "57x57",
"density": "0.75" "type": "image\/png"
}, },
{ {
"src": "\/android-icon-48x48.png", "src": "/static/images/favicons/apple-icon-60x60.png",
"sizes": "48x48", "sizes": "60x60",
"type": "image\/png", "type": "image\/png"
"density": "1.0" },
}, {
{ "src": "/static/images/favicons/apple-icon-72x72.png",
"src": "\/android-icon-72x72.png", "sizes": "72x72",
"sizes": "72x72", "type": "image\/png"
"type": "image\/png", },
"density": "1.5" {
}, "src": "/static/images/favicons/apple-icon-76x76.png",
{ "sizes": "76x76",
"src": "\/android-icon-96x96.png", "type": "image\/png"
"sizes": "96x96", },
"type": "image\/png", {
"density": "2.0" "src": "/static/images/favicons/apple-icon-114x114.png",
}, "sizes": "114x114",
{ "type": "image\/png"
"src": "\/android-icon-144x144.png", },
"sizes": "144x144", {
"type": "image\/png", "src": "/static/images/favicons/apple-icon-120x120.png",
"density": "3.0" "sizes": "120x120",
}, "type": "image\/png"
{ },
"src": "\/android-icon-192x192.png", {
"sizes": "192x192", "src": "/static/images/favicons/apple-icon-144x144.png",
"type": "image\/png", "sizes": "144x144",
"density": "4.0" "type": "image\/png"
} },
] {
"src": "/static/images/favicons/apple-icon-152x152.png",
"sizes": "152x152",
"type": "image\/png"
},
{
"src": "/static/images/favicons/apple-icon-180x180.png",
"sizes": "180x180",
"type": "image\/png"
},
{
"src": "/static/images/favicons/android-icon-36x36.png",
"sizes": "36x36",
"type": "image\/png",
"density": "0.75"
},
{
"src": "/static/images/favicons/android-icon-48x48.png",
"sizes": "48x48",
"type": "image\/png",
"density": "1.0"
},
{
"src": "/static/images/favicons/android-icon-72x72.png",
"sizes": "72x72",
"type": "image\/png",
"density": "1.5"
},
{
"src": "/static/images/favicons/favicon-16x16.png",
"sizes": "16x16",
"type": "image\/png",
"density": "1"
},
{
"src": "/static/images/favicons/favicon-32x32.png",
"sizes": "32x32",
"type": "image\/png",
"density": "1.5"
},
{
"src": "/static/images/favicons/favicon-96x96.png",
"sizes": "96x96",
"type": "image\/png",
"density": "2.0"
},
{
"src": "/static/images/favicons/android-icon-36x36.png",
"sizes": "36x36",
"type": "image\/png",
"density": "1"
},
{
"src": "/static/images/favicons/android-icon-48x48.png",
"sizes": "48x48",
"type": "image\/png",
"density": "1"
},
{
"src": "/static/images/favicons/android-icon-72x72.png",
"sizes": "72x72",
"type": "image\/png",
"density": "1.5"
},
{
"src": "/static/images/favicons/android-icon-96x96.png",
"sizes": "96x96",
"type": "image\/png",
"density": "2.0"
},
{
"src": "/static/images/favicons/android-icon-144x144.png",
"sizes": "144x144",
"type": "image\/png",
"density": "3.0"
},
{
"src": "/static/images/favicons/android-icon-192x192.png",
"sizes": "192x192",
"type": "image\/png",
"density": "4.0"
}
],
"start_url": "/",
"background_color": "#000000",
"display_override": ["window-control-overlay", "minimal-ui"],
"display": "standalone",
"scope": "/",
"theme_color": "#000000",
"shortcuts": [
{
"name": "WorkAdventures",
"short_name": "WA",
"description": "WorkAdventure application",
"url": "/",
"icons": [{ "src": "/static/images/favicons/android-icon-192x192.png", "sizes": "192x192" }]
}
],
"description": "WorkAdventure application",
"screenshots": [],
"related_applications": [{
"platform": "web",
"url": "https://workadventu.re"
}, {
"platform": "play",
"url": "https://play.workadventu.re"
}]
} }

View File

@ -89,10 +89,7 @@ export class GameManager {
console.log('starting '+ (this.currentGameSceneName || this.startRoom.id)) console.log('starting '+ (this.currentGameSceneName || this.startRoom.id))
scenePlugin.start(this.currentGameSceneName || this.startRoom.id); scenePlugin.start(this.currentGameSceneName || this.startRoom.id);
scenePlugin.launch(MenuSceneName); scenePlugin.launch(MenuSceneName);
scenePlugin.launch(HelpCameraSettingsSceneName);//700
if (!localUserStore.getHelpCameraSettingsShown()) {
scenePlugin.launch(HelpCameraSettingsSceneName);//700
}
} }
public gameSceneIsCreated(scene: GameScene) { public gameSceneIsCreated(scene: GameScene) {

View File

@ -206,7 +206,6 @@ export class GameScene extends ResizableScene implements CenterListener {
//hook preload scene //hook preload scene
preload(): void { preload(): void {
addLoader(this);
const localUser = localUserStore.getLocalUser(); const localUser = localUserStore.getLocalUser();
const textures = localUser?.textures; const textures = localUser?.textures;
if (textures) { if (textures) {
@ -266,6 +265,9 @@ export class GameScene extends ResizableScene implements CenterListener {
this.load.spritesheet('layout_modes', 'resources/objects/layout_modes.png', {frameWidth: 32, frameHeight: 32}); 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'); this.load.bitmapFont('main_font', 'resources/fonts/arcade.png', 'resources/fonts/arcade.xml');
//this function must stay at the end of preload function
addLoader(this);
} }
// FIXME: we need to put a "unknown" instead of a "any" and validate the structure of the JSON we are receiving. // FIXME: we need to put a "unknown" instead of a "any" and validate the structure of the JSON we are receiving.
@ -435,8 +437,8 @@ export class GameScene extends ResizableScene implements CenterListener {
//create input to move //create input to move
mediaManager.setUserInputManager(this.userInputManager);
this.userInputManager = new UserInputManager(this); this.userInputManager = new UserInputManager(this);
mediaManager.setUserInputManager(this.userInputManager);
if (localUserStore.getFullscreen()) { if (localUserStore.getFullscreen()) {
document.querySelector('body')?.requestFullscreen(); document.querySelector('body')?.requestFullscreen();
@ -1198,7 +1200,7 @@ ${escapedMessage}
* @param delta The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate. * @param delta The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate.
*/ */
update(time: number, delta: number) : void { update(time: number, delta: number) : void {
mediaManager.setLastUpdateScene(); mediaManager.updateScene();
this.currentTick = time; this.currentTick = time;
this.CurrentPlayer.moveUser(delta); this.CurrentPlayer.moveUser(delta);

View File

@ -35,8 +35,6 @@ export class CustomizeScene extends AbstractCharacterScene {
} }
preload() { preload() {
addLoader(this);
this.load.html(customizeSceneKey, 'resources/html/CustomCharacterScene.html'); this.load.html(customizeSceneKey, 'resources/html/CustomCharacterScene.html');
this.layers = loadAllLayers(this.load); this.layers = loadAllLayers(this.load);
@ -48,6 +46,9 @@ export class CustomizeScene extends AbstractCharacterScene {
this.layers[bodyResourceDescription.level].unshift(bodyResourceDescription); this.layers[bodyResourceDescription.level].unshift(bodyResourceDescription);
}); });
}); });
//this function must stay at the end of preload function
addLoader(this);
} }
create() { create() {

View File

@ -247,8 +247,7 @@ export class EnableCameraScene extends Phaser.Scene {
update(time: number, delta: number): void { update(time: number, delta: number): void {
this.soundMeterSprite.setVolume(this.soundMeter.getVolume()); this.soundMeterSprite.setVolume(this.soundMeter.getVolume());
mediaManager.updateScene();
mediaManager.setLastUpdateScene();
const middleX = this.getMiddleX(); const middleX = this.getMiddleX();
this.tweens.add({ this.tweens.add({

View File

@ -6,7 +6,6 @@ import {EnableCameraSceneName} from "./EnableCameraScene";
import {CustomizeSceneName} from "./CustomizeScene"; import {CustomizeSceneName} from "./CustomizeScene";
import {localUserStore} from "../../Connexion/LocalUserStore"; import {localUserStore} from "../../Connexion/LocalUserStore";
import {loadAllDefaultModels} from "../Entity/PlayerTexturesLoadingManager"; import {loadAllDefaultModels} from "../Entity/PlayerTexturesLoadingManager";
import {addLoader} from "../Components/Loader";
import {BodyResourceDescriptionInterface} from "../Entity/PlayerTextures"; import {BodyResourceDescriptionInterface} from "../Entity/PlayerTextures";
import {AbstractCharacterScene} from "./AbstractCharacterScene"; import {AbstractCharacterScene} from "./AbstractCharacterScene";
import {areCharacterLayersValid} from "../../Connexion/LocalUser"; import {areCharacterLayersValid} from "../../Connexion/LocalUser";

View File

@ -37,8 +37,6 @@ export class SelectCharacterScene extends AbstractCharacterScene {
} }
preload() { preload() {
addLoader(this);
this.load.html(selectCharacterKey, 'resources/html/selectCharacterScene.html'); this.load.html(selectCharacterKey, 'resources/html/selectCharacterScene.html');
this.loadSelectSceneCharacters().then((bodyResourceDescriptions) => { this.loadSelectSceneCharacters().then((bodyResourceDescriptions) => {
@ -47,6 +45,8 @@ export class SelectCharacterScene extends AbstractCharacterScene {
}); });
}) })
this.playerModels = loadAllDefaultModels(this.load); this.playerModels = loadAllDefaultModels(this.load);
//this function must stay at the end of preload function
addLoader(this); addLoader(this);
} }

View File

@ -31,14 +31,13 @@ export class SelectCompanionScene extends ResizableScene {
} }
preload() { preload() {
addLoader(this);
this.load.html(selectCompanionSceneKey, 'resources/html/SelectCompanionScene.html'); this.load.html(selectCompanionSceneKey, 'resources/html/SelectCompanionScene.html');
getAllCompanionResources(this.load).forEach(model => { getAllCompanionResources(this.load).forEach(model => {
this.companionModels.push(model); this.companionModels.push(model);
}); });
//this function must stay at the end of preload function
addLoader(this); addLoader(this);
} }

View File

@ -21,7 +21,6 @@ export class HelpCameraSettingsScene extends Phaser.Scene {
} }
create(){ create(){
localUserStore.setHelpCameraSettingsShown();
this.createHelpCameraSettings(); this.createHelpCameraSettings();
} }
@ -31,6 +30,9 @@ export class HelpCameraSettingsScene extends Phaser.Scene {
this.revealMenusAfterInit(this.helpCameraSettingsElement, helpCameraSettings); this.revealMenusAfterInit(this.helpCameraSettingsElement, helpCameraSettings);
this.helpCameraSettingsElement.addListener('click'); this.helpCameraSettingsElement.addListener('click');
this.helpCameraSettingsElement.on('click', (event:MouseEvent) => { this.helpCameraSettingsElement.on('click', (event:MouseEvent) => {
if((event?.target as HTMLInputElement).id === 'mailto') {
return;
}
event.preventDefault(); event.preventDefault();
if((event?.target as HTMLInputElement).id === 'helpCameraSettingsFormRefresh') { if((event?.target as HTMLInputElement).id === 'helpCameraSettingsFormRefresh') {
window.location.reload(); window.location.reload();
@ -39,18 +41,27 @@ export class HelpCameraSettingsScene extends Phaser.Scene {
} }
}); });
if(!mediaManager.constraintsMedia.audio || !mediaManager.constraintsMedia.video){ if(!localUserStore.getHelpCameraSettingsShown() && (!mediaManager.constraintsMedia.audio || !mediaManager.constraintsMedia.video)){
this.openHelpCameraSettingsOpened(); this.openHelpCameraSettingsOpened();
localUserStore.setHelpCameraSettingsShown();
} }
mediaManager.setHelpCameraSettingsCallBack(() => {
this.openHelpCameraSettingsOpened();
});
} }
private openHelpCameraSettingsOpened(): void{ private openHelpCameraSettingsOpened(): void{
HtmlUtils.getElementByIdOrFail<HTMLDivElement>('webRtcSetup').style.display = 'none'; HtmlUtils.getElementByIdOrFail<HTMLDivElement>('webRtcSetup').style.display = 'none';
this.helpCameraSettingsOpened = true; this.helpCameraSettingsOpened = true;
if(window.navigator.userAgent.includes('Firefox')){ try{
HtmlUtils.getElementByIdOrFail<HTMLParagraphElement>('browserHelpSetting').innerHTML ='<img src="/resources/objects/help-setting-camera-permission-firefox.png"/>'; if(window.navigator.userAgent.includes('Firefox')){
}else if(window.navigator.userAgent.includes('Chrome')){ HtmlUtils.getElementByIdOrFail<HTMLParagraphElement>('browserHelpSetting').innerHTML ='<img src="/resources/objects/help-setting-camera-permission-firefox.png"/>';
HtmlUtils.getElementByIdOrFail<HTMLParagraphElement>('browserHelpSetting').innerHTML ='<img src="/resources/objects/help-setting-camera-permission-chrome.png"/>'; }else if(window.navigator.userAgent.includes('Chrome')){
HtmlUtils.getElementByIdOrFail<HTMLParagraphElement>('browserHelpSetting').innerHTML ='<img src="/resources/objects/help-setting-camera-permission-chrome.png"/>';
}
}catch(err) {
console.error('openHelpCameraSettingsOpened => getElementByIdOrFail => error', err);
} }
const middleY = this.getMiddleY(); const middleY = this.getMiddleY();
const middleX = this.getMiddleX(); const middleX = this.getMiddleX();
@ -66,13 +77,13 @@ export class HelpCameraSettingsScene extends Phaser.Scene {
private closeHelpCameraSettingsOpened(): void{ private closeHelpCameraSettingsOpened(): void{
const middleX = this.getMiddleX(); const middleX = this.getMiddleX();
const helpCameraSettingsInfo = this.helpCameraSettingsElement.getChildByID('helpCameraSettings') as HTMLParagraphElement; /*const helpCameraSettingsInfo = this.helpCameraSettingsElement.getChildByID('helpCameraSettings') as HTMLParagraphElement;
helpCameraSettingsInfo.innerText = ''; helpCameraSettingsInfo.innerText = '';
helpCameraSettingsInfo.style.display = 'none'; helpCameraSettingsInfo.style.display = 'none';*/
this.helpCameraSettingsOpened = false; this.helpCameraSettingsOpened = false;
this.tweens.add({ this.tweens.add({
targets: this.helpCameraSettingsElement, targets: this.helpCameraSettingsElement,
y: -400, y: -1000,
x: middleX, x: middleX,
duration: 1000, duration: 1000,
ease: 'Power3', ease: 'Power3',
@ -89,15 +100,17 @@ export class HelpCameraSettingsScene extends Phaser.Scene {
} }
update(time: number, delta: number): void { update(time: number, delta: number): void {
const middleX = this.getMiddleX(); if(this.helpCameraSettingsOpened){
const middleY = this.getMiddleY(); const middleX = this.getMiddleX();
this.tweens.add({ const middleY = this.getMiddleY();
targets: this.helpCameraSettingsElement, this.tweens.add({
x: middleX, targets: this.helpCameraSettingsElement,
y: middleY, x: middleX,
duration: 1000, y: middleY,
ease: 'Power3' duration: 1000,
}); ease: 'Power3'
});
}
} }
public onResize(ev: UIEvent): void { public onResize(ev: UIEvent): void {

View File

@ -346,7 +346,7 @@ class LayoutManager {
userInputManager.addSpaceEventListner(callBack); userInputManager.addSpaceEventListner(callBack);
} }
public removeActionButton(id: string, userInputManager: UserInputManager){ public removeActionButton(id: string, userInputManager?: UserInputManager){
//delete previous element //delete previous element
const previousDiv = this.actionButtonInformation.get(id); const previousDiv = this.actionButtonInformation.get(id);
if(previousDiv){ if(previousDiv){
@ -354,10 +354,45 @@ class LayoutManager {
this.actionButtonInformation.delete(id); this.actionButtonInformation.delete(id);
} }
const previousEventCallback = this.actionButtonTrigger.get(id); const previousEventCallback = this.actionButtonTrigger.get(id);
if(previousEventCallback){ if(previousEventCallback && userInputManager){
userInputManager.removeSpaceEventListner(previousEventCallback); userInputManager.removeSpaceEventListner(previousEventCallback);
} }
} }
public addInformation(id: string, text: string, callBack?: Function, userInputManager?: UserInputManager){
//delete previous element
for ( const [key, value] of this.actionButtonInformation ) {
this.removeActionButton(key, userInputManager);
}
//create div and text html component
const p = document.createElement('p');
p.classList.add('action-body');
p.innerText = text;
const div = document.createElement('div');
div.classList.add('action');
div.classList.add(id);
div.id = id;
div.appendChild(p);
this.actionButtonInformation.set(id, div);
const mainContainer = HtmlUtils.getElementByIdOrFail<HTMLDivElement>('main-container');
mainContainer.appendChild(div);
//add trigger action
if(callBack){
div.onpointerdown = () => {
callBack();
this.removeActionButton(id, userInputManager);
};
}
//remove it after 10 sec
setTimeout(() => {
this.removeActionButton(id, userInputManager);
}, 10000)
}
} }
const layoutManager = new LayoutManager(); const layoutManager = new LayoutManager();

View File

@ -4,6 +4,8 @@ import {discussionManager, SendMessageCallback} from "./DiscussionManager";
import {UserInputManager} from "../Phaser/UserInput/UserInputManager"; import {UserInputManager} from "../Phaser/UserInput/UserInputManager";
import {localUserStore} from "../Connexion/LocalUserStore"; import {localUserStore} from "../Connexion/LocalUserStore";
import {UserSimplePeerInterface} from "./SimplePeer"; import {UserSimplePeerInterface} from "./SimplePeer";
import {SoundMeter} from "../Phaser/Components/SoundMeter";
declare const navigator:any; // eslint-disable-line @typescript-eslint/no-explicit-any declare const navigator:any; // eslint-disable-line @typescript-eslint/no-explicit-any
let videoConstraint: boolean|MediaTrackConstraints = { let videoConstraint: boolean|MediaTrackConstraints = {
@ -26,6 +28,7 @@ export type StartScreenSharingCallback = (media: MediaStream) => void;
export type StopScreenSharingCallback = (media: MediaStream) => void; export type StopScreenSharingCallback = (media: MediaStream) => void;
export type ReportCallback = (message: string) => void; export type ReportCallback = (message: string) => void;
export type ShowReportCallBack = (userId: string, userName: string|undefined) => void; export type ShowReportCallBack = (userId: string, userName: string|undefined) => void;
export type HelpCameraSettingsCallBack = () => void;
// TODO: Split MediaManager in 2 classes: MediaManagerUI (in charge of HTML) and MediaManager (singleton in charge of the camera only) // TODO: Split MediaManager in 2 classes: MediaManagerUI (in charge of HTML) and MediaManager (singleton in charge of the camera only)
export class MediaManager { export class MediaManager {
@ -40,6 +43,7 @@ export class MediaManager {
microphoneClose: HTMLImageElement; microphoneClose: HTMLImageElement;
microphone: HTMLImageElement; microphone: HTMLImageElement;
webrtcInAudio: HTMLAudioElement; webrtcInAudio: HTMLAudioElement;
mySoundMeterElement: HTMLDivElement;
private webrtcOutAudio: HTMLAudioElement; private webrtcOutAudio: HTMLAudioElement;
constraintsMedia : MediaStreamConstraints = { constraintsMedia : MediaStreamConstraints = {
audio: audioConstraint, audio: audioConstraint,
@ -49,6 +53,8 @@ export class MediaManager {
startScreenSharingCallBacks : Set<StartScreenSharingCallback> = new Set<StartScreenSharingCallback>(); startScreenSharingCallBacks : Set<StartScreenSharingCallback> = new Set<StartScreenSharingCallback>();
stopScreenSharingCallBacks : Set<StopScreenSharingCallback> = new Set<StopScreenSharingCallback>(); stopScreenSharingCallBacks : Set<StopScreenSharingCallback> = new Set<StopScreenSharingCallback>();
showReportModalCallBacks : Set<ShowReportCallBack> = new Set<ShowReportCallBack>(); showReportModalCallBacks : Set<ShowReportCallBack> = new Set<ShowReportCallBack>();
helpCameraSettingsCallBacks : Set<HelpCameraSettingsCallBack> = new Set<HelpCameraSettingsCallBack>();
private microphoneBtn: HTMLDivElement; private microphoneBtn: HTMLDivElement;
private cinemaBtn: HTMLDivElement; private cinemaBtn: HTMLDivElement;
private monitorBtn: HTMLDivElement; private monitorBtn: HTMLDivElement;
@ -63,6 +69,12 @@ export class MediaManager {
private triggerCloseJistiFrame : Map<String, Function> = new Map<String, Function>(); private triggerCloseJistiFrame : Map<String, Function> = new Map<String, Function>();
private userInputManager?: UserInputManager;
private mySoundMeter?: SoundMeter|null;
private soundMeters: Map<string, SoundMeter> = new Map<string, SoundMeter>();
private soundMeterElements: Map<string, HTMLDivElement> = new Map<string, HTMLDivElement>();
constructor() { constructor() {
this.myCamVideo = HtmlUtils.getElementByIdOrFail<HTMLVideoElement>('myCamVideo'); this.myCamVideo = HtmlUtils.getElementByIdOrFail<HTMLVideoElement>('myCamVideo');
@ -121,10 +133,16 @@ export class MediaManager {
this.pingCameraStatus(); this.pingCameraStatus();
this.checkActiveUser(); //todo: desactivated in case of bug this.checkActiveUser(); //todo: desactivated in case of bug
this.mySoundMeterElement = (HtmlUtils.getElementByIdOrFail('mySoundMeter'));
this.mySoundMeterElement.childNodes.forEach((value: ChildNode, index) => {
this.mySoundMeterElement.children.item(index)?.classList.remove('active');
});
} }
public setLastUpdateScene(){ public updateScene(){
this.lastUpdateScene = new Date(); this.lastUpdateScene = new Date();
this.updateSoudMeter();
} }
public blurCamera() { public blurCamera() {
@ -225,6 +243,10 @@ export class MediaManager {
}).catch((err) => { }).catch((err) => {
console.error(err); console.error(err);
this.disableCameraStyle(); this.disableCameraStyle();
layoutManager.addInformation('warning', 'Camera access denied. Click here and check navigators permissions.', () => {
this.showHelpCameraSettingsCallBack();
}, this.userInputManager);
}); });
} }
@ -253,6 +275,10 @@ export class MediaManager {
}).catch((err) => { }).catch((err) => {
console.error(err); console.error(err);
this.disableMicrophoneStyle(); this.disableMicrophoneStyle();
layoutManager.addInformation('warning', 'Microphone access denied. Click here and check navigators permissions.', () => {
this.showHelpCameraSettingsCallBack();
}, this.userInputManager);
}); });
} }
@ -324,6 +350,10 @@ export class MediaManager {
this.monitorClose.style.display = "block"; this.monitorClose.style.display = "block";
this.monitor.style.display = "none"; this.monitor.style.display = "none";
this.monitorBtn.classList.remove("enabled"); this.monitorBtn.classList.remove("enabled");
layoutManager.addInformation('warning', 'Screen sharing access denied. Click here and check navigators permissions.', () => {
this.showHelpCameraSettingsCallBack();
}, this.userInputManager);
}); });
} }
@ -402,13 +432,14 @@ export class MediaManager {
} }
} }
return this.getLocalStream().catch(() => { return this.getLocalStream().catch((err) => {
console.info('Error get camera, trying with video option at null'); console.info('Error get camera, trying with video option at null =>', err);
this.disableCameraStyle(); this.disableCameraStyle();
return this.getLocalStream().then((stream : MediaStream) => { return this.getLocalStream().then((stream : MediaStream) => {
this.hasCamera = false; this.hasCamera = false;
return stream; return stream;
}).catch((err) => { }).catch((err) => {
this.disableMicrophoneStyle();
console.info("error get media ", this.constraintsMedia.video, this.constraintsMedia.audio, err); console.info("error get media ", this.constraintsMedia.video, this.constraintsMedia.audio, err);
throw err; throw err;
}); });
@ -425,6 +456,13 @@ export class MediaManager {
return navigator.mediaDevices.getUserMedia(this.constraintsMedia).then((stream : MediaStream) => { return navigator.mediaDevices.getUserMedia(this.constraintsMedia).then((stream : MediaStream) => {
this.localStream = stream; this.localStream = stream;
this.myCamVideo.srcObject = this.localStream; this.myCamVideo.srcObject = this.localStream;
//init sound meter
this.mySoundMeter = null;
if(this.constraintsMedia.audio){
this.mySoundMeter = new SoundMeter();
this.mySoundMeter.connectToSource(stream, new AudioContext());
}
return stream; return stream;
}).catch((err: Error) => { }).catch((err: Error) => {
throw err; throw err;
@ -451,6 +489,7 @@ export class MediaManager {
track.stop(); track.stop();
} }
} }
this.mySoundMeter?.stop();
} }
setCamera(id: string): Promise<MediaStream> { setCamera(id: string): Promise<MediaStream> {
@ -496,6 +535,13 @@ export class MediaManager {
</button> </button>
<video id="${userId}" autoplay></video> <video id="${userId}" autoplay></video>
<img src="resources/logos/blockSign.svg" id="blocking-${userId}" class="block-logo"> <img src="resources/logos/blockSign.svg" id="blocking-${userId}" class="block-logo">
<div id="soundMeter-${userId}" class="sound-progress">
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
</div> </div>
`; `;
@ -585,6 +631,12 @@ export class MediaManager {
throw `Unable to find video for ${userId}`; throw `Unable to find video for ${userId}`;
} }
remoteVideo.srcObject = stream; remoteVideo.srcObject = stream;
//sound metter
const soundMeter = new SoundMeter();
soundMeter.connectToSource(stream, new AudioContext());
this.soundMeters.set(userId, soundMeter);
this.soundMeterElements.set(userId, HtmlUtils.getElementByIdOrFail<HTMLImageElement>('soundMeter-'+userId));
} }
addStreamRemoteScreenSharing(userId: string, stream : MediaStream){ addStreamRemoteScreenSharing(userId: string, stream : MediaStream){
// In the case of screen sharing (going both ways), we may need to create the HTML element if it does not exist yet // In the case of screen sharing (going both ways), we may need to create the HTML element if it does not exist yet
@ -600,6 +652,10 @@ export class MediaManager {
layoutManager.remove(userId); layoutManager.remove(userId);
this.remoteVideo.delete(userId); this.remoteVideo.delete(userId);
this.soundMeters.get(userId)?.stop();
this.soundMeters.delete(userId);
this.soundMeterElements.delete(userId);
//permit to remove user in discussion part //permit to remove user in discussion part
this.removeParticipant(userId); this.removeParticipant(userId);
} }
@ -717,6 +773,7 @@ export class MediaManager {
} }
public setUserInputManager(userInputManager : UserInputManager){ public setUserInputManager(userInputManager : UserInputManager){
this.userInputManager = userInputManager;
discussionManager.setUserInputManager(userInputManager); discussionManager.setUserInputManager(userInputManager);
} }
//check if user is active //check if user is active
@ -739,6 +796,57 @@ export class MediaManager {
public setShowReportModalCallBacks(callback: ShowReportCallBack){ public setShowReportModalCallBacks(callback: ShowReportCallBack){
this.showReportModalCallBacks.add(callback); this.showReportModalCallBacks.add(callback);
} }
public setHelpCameraSettingsCallBack(callback: HelpCameraSettingsCallBack){
this.helpCameraSettingsCallBacks.add(callback);
}
private showHelpCameraSettingsCallBack(){
for(const callBack of this.helpCameraSettingsCallBacks){
callBack();
}
}
updateSoudMeter(){
try{
const volume = parseInt(((this.mySoundMeter ? this.mySoundMeter.getVolume() : 0) / 10).toFixed(0));
this.setVolumeSoundMeter(volume, this.mySoundMeterElement);
for(const indexUserId of this.soundMeters.keys()){
const soundMeter = this.soundMeters.get(indexUserId);
const soundMeterElement = this.soundMeterElements.get(indexUserId);
if(!soundMeter || !soundMeterElement){
return;
}
const volumeByUser = parseInt((soundMeter.getVolume() / 10).toFixed(0));
this.setVolumeSoundMeter(volumeByUser, soundMeterElement);
}
}catch(err){
//console.error(err);
}
}
private setVolumeSoundMeter(volume: number, element: HTMLDivElement){
if(volume <= 0 && !element.classList.contains('active')){
return;
}
element.classList.remove('active');
if(volume <= 0){
return;
}
element.classList.add('active');
element.childNodes.forEach((value: ChildNode, index) => {
const elementChildre = element.children.item(index);
if(!elementChildre){
return;
}
elementChildre.classList.remove('active');
if((index +1) > volume){
return;
}
elementChildre.classList.add('active');
});
}
} }
export const mediaManager = new MediaManager(); export const mediaManager = new MediaManager();

View File

@ -82,15 +82,11 @@ export class SimplePeer {
}); });
mediaManager.showGameOverlay(); mediaManager.showGameOverlay();
mediaManager.getCamera().then(() => { mediaManager.getCamera().finally(() => {
//receive message start //receive message start
this.Connection.receiveWebrtcStart((message: UserSimplePeerInterface) => { this.Connection.receiveWebrtcStart((message: UserSimplePeerInterface) => {
this.receiveWebrtcStart(message); this.receiveWebrtcStart(message);
}); });
}).catch((err) => {
console.error("err", err);
}); });
this.Connection.disconnectMessage((data: WebRtcDisconnectMessageInterface): void => { this.Connection.disconnectMessage((data: WebRtcDisconnectMessageInterface): void => {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

File diff suppressed because one or more lines are too long

BIN
maps/Village/logo-WA.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
maps/Village/tileset1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

@ -183,7 +183,7 @@ export class IoSocketController {
console.warn('Cannot find user with uuid "'+userUuid+'". Performing an anonymous login instead.'); console.warn('Cannot find user with uuid "'+userUuid+'". Performing an anonymous login instead.');
} else if(err?.response?.status == 403) { } else if(err?.response?.status == 403) {
// If we get an HTTP 404, the world is full. We need to broadcast a special error to the client. // If we get an HTTP 404, the world is full. We need to broadcast a special error to the client.
// we finish immediatly the upgrade then we will close the socket as soon as it starts opening. // we finish immediately the upgrade then we will close the socket as soon as it starts opening.
return res.upgrade({ return res.upgrade({
rejected: true, rejected: true,
message: err?.response?.data.message, message: err?.response?.data.message,
@ -200,15 +200,15 @@ export class IoSocketController {
memberTags = userData.tags; memberTags = userData.tags;
memberTextures = userData.textures; memberTextures = userData.textures;
if (!room.public && room.policyType === GameRoomPolicyTypes.USE_TAGS_POLICY && (userData.anonymous === true || !room.canAccess(memberTags))) { if (!room.public && room.policyType === GameRoomPolicyTypes.USE_TAGS_POLICY && (userData.anonymous === true || !room.canAccess(memberTags))) {
throw new Error('No correct tags') throw new Error('Insufficient privileges to access this room')
} }
if (!room.public && room.policyType === GameRoomPolicyTypes.MEMBERS_ONLY_POLICY && userData.anonymous === true) { if (!room.public && room.policyType === GameRoomPolicyTypes.MEMBERS_ONLY_POLICY && userData.anonymous === true) {
throw new Error('No correct member') throw new Error('Use the login URL to connect')
} }
} catch (e) { } catch (e) {
console.log('access not granted for user '+userUuid+' and room '+roomId); console.log('access not granted for user '+userUuid+' and room '+roomId);
console.error(e); console.error(e);
throw new Error('User cannot acces on this world') throw new Error('User cannot access this world')
} }
} }
@ -283,7 +283,7 @@ export class IoSocketController {
ws.close(); ws.close();
return; return;
} }
// Let's join the room // Let's join the room
const client = this.initClient(ws); const client = this.initClient(ws);
socketManager.handleJoinRoom(client); socketManager.handleJoinRoom(client);