Merge pull request #990 from thecodingmachine/develop
Release 04/05 - WorkAdventure Village - Fix loader - Create sound meter
19
front/dist/index.tmpl.html
vendored
@ -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>
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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>
|
||||||
|
18
front/dist/resources/style/mobile-style.scss
vendored
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
94
front/dist/resources/style/style.css
vendored
@ -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;
|
||||||
|
186
front/dist/static/images/favicons/manifest.json
vendored
@ -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"
|
||||||
|
}]
|
||||||
}
|
}
|
@ -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) {
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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() {
|
||||||
|
@ -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({
|
||||||
|
@ -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";
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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();
|
||||||
|
@ -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();
|
||||||
|
@ -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 => {
|
||||||
|
Before Width: | Height: | Size: 3.8 KiB |
BIN
maps/Village/logo-WA.png
Normal file
After Width: | Height: | Size: 5.1 KiB |
BIN
maps/Village/sol_intérieur.png
Normal file
After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 3.0 KiB |
BIN
maps/Village/tileset1-repositioning.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
maps/Village/tileset1.png
Normal file
After Width: | Height: | Size: 29 KiB |
@ -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);
|
||||||
|