diff --git a/WebServers/SignallingWebServer/Public/player.css b/WebServers/SignallingWebServer/Public/player.css index 552fd1c..2c5259f 100644 --- a/WebServers/SignallingWebServer/Public/player.css +++ b/WebServers/SignallingWebServer/Public/player.css @@ -1,378 +1,462 @@ /*Copyright Epic Games, Inc. All Rights Reserved.*/ +@import url(./fonts/fonts.css); + :root { - /*Using colour scheme https://color.adobe.com/TD-Colors---Option-3-color-theme-10394433/*/ - --colour1: #000000; - --colour2: #ffffff; - --colour3: #0585fe; - --colour4: #35b350; - --colour5: #ffab00; - --colour6: #1e1d22; - --colour7: #3c3b40; + /*Using colour scheme https://color.adobe.com/TD-Colors---Option-3-color-theme-10394433/*/ + --colour1: #151619; + ; + --colour2: #FFFFFF; + --colour3: #0585fe; + --colour4: #35b350; + --colour5: #ffab00; + --colour6: #1e1d22; + --colour7: #3c3b40; +} + +#loader { + width: 106px; + height: 106px; + border-radius: 50%; + display: inline-block; + position: relative; + background: conic-gradient(from 135deg at 50% 50%, + rgba(255, 255, 255, 0) -6.26deg, + #ffffff 314.83deg, + rgba(255, 255, 255, 0) 353.74deg, + #ffffff 674.83deg); + box-sizing: border-box; + animation: rotation 1s linear infinite; +} + + +@keyframes rotation { + 0% { + transform: rotate(0deg); + + } + + 100% { + transform: rotate(360deg); + } + +} + +#loader::after { + content: ""; + box-sizing: border-box; + position: absolute; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); + width: 100px; + height: 100px; + border-radius: 50%; + background: #151619; } body { - margin: 0px; - background-color: black; - font-family: "Montserrat", sans-serif; + margin: 0px; + background-color: #151619; + + font-family: 'Montserrat', sans-serif; +} + +h2 { + font-family: "GilroyWebRegular"; } #playerUI { - width: 100%; - height: 100%; + width: 100%; + height: 100%; } canvas { - image-rendering: crisp-edges; - position: absolute; + image-rendering: crisp-edges; + position: absolute; } video { - position: absolute; - width: 100%; - height: 100%; + position: absolute; + width: 100%; + height: 100%; } #player { - width: 100%; - height: 100%; - position: absolute; - background-color: #000; + width: 100%; + height: 100%; + position: absolute; } #videoPlayOverlay { - position: absolute; - font-size: 1.8em; - width: 100%; - height: 100%; - color: var(--colour2); + position: absolute; + font-size: 1.8em; + width: 100%; + height: 100%; + color: var(--colour2) } /* State for element to be clickable */ .clickableState { - align-items: center; - justify-content: center; - display: flex; - cursor: pointer; + align-items: center; + justify-content: center; + display: flex; } /* State for element to show text, this is for informational use*/ .textDisplayState { - align-items: center; - justify-content: center; - display: flex; - cursor: pointer; + align-items: center; + justify-content: center; + display: flex; + cursor: pointer; } /* State to hide overlay, WebRTC communication is in progress and or is playing */ .hiddenState { - display: none; + display: none; } #playButton { - font-family: "Inter", sans-serif; - display: flex; - flex-direction: column; - gap: 8px; - z-index: 30; - background: #262626; - width: 494px; - height: 282px; - border: 1px solid #404040; - border-radius: 32px; - align-items: center; - justify-content: center; + display: block; + width: 88px; + height: 88px; + z-index: 30; + backdrop-filter: blur(10px); + border-radius: 112px; + cursor: pointer; } -.caption { - font-style: normal; - font-weight: 400; - font-size: 22px; - line-height: 130%; - /* identical to box height, or 29px */ - text-align: center; - /* Landing/White */ - margin: 0; - color: #ebebeb; +#container { + width: 400px; + height: 100%; + justify-content: center; + /* Background */ + background: transparent; + /* Button_1 */ + border-width: 0px 2px; + border-style: solid; + border-color: #23242A; + display: flex; + flex-direction: column; + align-items: center; + gap: 40px; + padding: 40px 56px; + box-sizing: border-box; } -.caption1 { - margin: 0; - font-style: normal; - font-weight: 400; - font-size: 14px; - line-height: 130%; - /* or 18px */ +@media screen and (max-width: 500px) { + #container { + width: 100%; + border: none; + } - text-align: center; - - /* Landing/LightGray */ - - color: #888888; } -.play-btn { - margin-top: 17px; - background: #454545; - border-radius: 50%; - outline: none; - border: none; - cursor: pointer; - width: 106px; - height: 106px; + + + + +#playButton:hover { + background: linear-gradient(180deg, #BC75FF 0%, #798FFF 100%); + backdrop-filter: blur(10px) } -img#playButton { - max-width: 241px; - width: 10%; +#title { + font-style: normal; + font-weight: 400; + font-size: 38px; + line-height: 100%; + /* or 38px */ + /* White */ + color: #F2F2F2; + margin: 0 0 16px 0; } +#caption { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-size: 16px; + line-height: 140%; + /* or 22px */ + text-align: center; + /* Inactive */ + color: #C5C7CE; + margin: 0; + text-align: left; + +} + +#link { + font-family: 'Inter'; + cursor: pointer; + background: #1C1D21; + border-radius: 4px; + width: 100%; + display: flex; + align-items: center; + justify-content: center; + text-decoration: none; + padding: 8px 16px; + box-sizing: border-box; + font-weight: 400; + font-size: 12px; + line-height: 130%; + /* identical to box height, or 16px */ + /* Inactive */ + color: #C5C7CE; +} + +#link:hover { + background: #23242A; +} + + #freezeFrameOverlay { - background-color: transparent; + background-color: transparent; } .freezeframeBackground { - background-color: #000 !important; + background-color: #000 !important; } #overlay { - width: 100%; - height: 100%; - z-index: 20; - position: absolute; - color: var(--colour2); - pointer-events: none; - overflow: hidden; + width: 100%; + height: 100%; + z-index: 20; + position: absolute; + color: var(--colour2); + pointer-events: none; + overflow: hidden; } #overlay button { - background-color: var(--colour7); - border: 1px solid var(--colour7); - color: var(--colour2); - position: relative; - width: 3rem; - height: 3rem; - padding: 0.5rem; - text-align: center; + background-color: var(--colour7); + border: 1px solid var(--colour7); + color: var(--colour2); + position: relative; + width: 3rem; + height: 3rem; + padding: 0.5rem; + text-align: center; } #fullscreen-btn { - padding: 0.6rem !important; + padding: 0.6rem !important; } #overlay button:hover { - background-color: var(--colour3); - border: 3px solid var(--colour3); - transition: 0.25s ease; - padding-left: 0.55rem; - padding-top: 0.55rem; + background-color: var(--colour3); + border: 3px solid var(--colour3); + transition: 0.25s ease; + padding-left: 0.55rem; + padding-top: 0.55rem; } #overlay button:active { - border: 3px solid var(--colour3); - background-color: var(--colour7); - padding-left: 0.55rem; - padding-top: 0.55rem; + border: 3px solid var(--colour3); + background-color: var(--colour7); + padding-left: 0.55rem; + padding-top: 0.55rem; } #overlay img { - width: 100%; - height: 100%; + width: 100%; + height: 100%; } .tooltip .tooltiptext { - visibility: hidden; - width: auto; - color: var(--colour2); - text-align: center; - border-radius: 15px; - padding: 0px 10px; - font-family: "Montserrat", sans-serif; - font-size: 0.75rem; - letter-spacing: 0.75px; - /* Position the tooltip */ - position: absolute; - top: 0; - transform: translateY(25%); - left: 125%; - z-index: 20; + visibility: hidden; + width: auto; + color: var(--colour2); + text-align: center; + border-radius: 15px; + padding: 0px 10px; + font-family: 'Montserrat', sans-serif; + font-size: 0.75rem; + letter-spacing: 0.75px; + /* Position the tooltip */ + position: absolute; + top: 0; + transform: translateY(25%); + left: 125%; + z-index: 20; } .tooltip:hover .tooltiptext { - visibility: visible; - background-color: var(--colour7); + visibility: visible; + background-color: var(--colour7); } #connection .tooltiptext { - top: 125%; - transform: translateX(-25%); - left: 0; - z-index: 20; - padding: 5px 10px; + top: 125%; + transform: translateX(-25%); + left: 0; + z-index: 20; + padding: 5px 10px; } #settings-panel .tooltiptext { - display: block; - top: 125%; - transform: translateX(-50%); - left: 0; - z-index: 20; - padding: 5px 10px; - border: 3px solid var(--colour5); - width: max-content; + display: block; + top: 125%; + transform: translateX(-50%); + left: 0; + z-index: 20; + padding: 5px 10px; + border: 3px solid var(--colour5); + width: max-content; } #controls { - position: absolute; - top: 2%; - left: 1%; - font-family: "Michroma", sans-serif; - pointer-events: all; - display: block; - visibility: hidden; + position: absolute; + top: 2%; + left: 1%; + font-family: 'Michroma', sans-serif; + pointer-events: all; + display: none; } -#controls > * { - margin-bottom: 0.5rem; - border-radius: 50%; - display: block; - height: 2rem; - line-height: 1.75rem; - padding: 0.5rem; +#controls>* { + margin-bottom: 0.5rem; + border-radius: 50%; + display: block; + height: 2rem; + line-height: 1.75rem; + padding: 0.5rem; } #controls #additionalinfo { - text-align: center; - font-family: "Montserrat", sans-serif; + text-align: center; + font-family: 'Montserrat', sans-serif; } #unrealengine { - visibility: hidden; - position: absolute; - bottom: 5%; - right: 10%; - font-family: "Michroma", sans-serif; - pointer-events: all; - width: min-content; + position: absolute; + bottom: 5%; + right: 10%; + font-family: 'Michroma', sans-serif; + pointer-events: all; + visibility: hidden; + width: min-content; } #unrealengine p { - visibility: hidden; - width: 15rem; + visibility: hidden; + width: 15rem; } #connection { - visibility: hidden; - position: absolute; - bottom: 5%; - left: 10%; - font-family: "Michroma", sans-serif; - height: 3rem; - width: 3rem; - pointer-events: all; + position: absolute; + bottom: 5%; + left: 10%; + font-family: 'Michroma', sans-serif; + height: 3rem; + width: 3rem; + pointer-events: none; + visibility: hidden; } .noselect { - -webkit-touch-callout: none; - /* iOS Safari */ - -webkit-user-select: none; - /* Safari */ - -khtml-user-select: none; - /* Konqueror HTML */ - -moz-user-select: none; - /* Old versions of Firefox */ - -ms-user-select: none; - /* Internet Explorer/Edge */ - user-select: none; - /* Non-prefixed version, currently + -webkit-touch-callout: none; + /* iOS Safari */ + -webkit-user-select: none; + /* Safari */ + -khtml-user-select: none; + /* Konqueror HTML */ + -moz-user-select: none; + /* Old versions of Firefox */ + -ms-user-select: none; + /* Internet Explorer/Edge */ + user-select: none; + /* Non-prefixed version, currently supported by Chrome, Edge, Opera and Firefox */ } .panel-wrap { - position: fixed; - top: 0; - bottom: 0; - right: 0; - height: 100%; - min-width: 20vw; - transform: translateX(100%); - transition: 0.3s ease-out; - pointer-events: all; - backdrop-filter: blur(10px); - -webkit-backdrop-filter: blur(10px); - overflow-y: auto; - overflow-x: hidden; - background-color: rgba(30, 29, 34, 0.5); + position: fixed; + top: 0; + bottom: 0; + right: 0; + height: 100%; + min-width: 20vw; + transform: translateX(100%); + transition: .3s ease-out; + pointer-events: all; + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); + overflow-y: auto; + overflow-x: hidden; + background-color: rgba(30, 29, 34, 0.5) } .panel-wrap-visible { - transform: translateX(0%); + transform: translateX(0%); } .panel { - color: #eee; - overflow-y: auto; - padding: 1em; + color: #eee; + overflow-y: auto; + padding: 1em; } #heading { - display: inline-block; - font-size: 2em; - margin-block-start: 0.67em; - margin-block-end: 0.67em; - margin-inline-start: 0px; - margin-inline-end: 0px; - position: relative; - padding: 0 0 0 2rem; + display: inline-block; + font-size: 2em; + margin-block-start: 0.67em; + margin-block-end: 0.67em; + margin-inline-start: 0px; + margin-inline-end: 0px; + position: relative; + padding: 0 0 0 2rem; } #close { - margin: 0.5rem; - padding-top: 0.5rem; - padding-bottom: 0.5rem; - padding-right: 0.5rem; - font-size: 2em; - float: right; + margin: 0.5rem; + padding-top: 0.5rem; + padding-bottom: 0.5rem; + padding-right: 0.5rem; + font-size: 2em; + float: right; } #close:after { - padding-left: 0.5rem; - display: inline-block; - content: "\00d7"; - /* This will render the 'X' */ + padding-left: 0.5rem; + display: inline-block; + content: "\00d7"; + /* This will render the 'X' */ } #close:hover { - color: var(--colour3); - transition: ease 0.3s; + color: var(--colour3); + transition: ease 0.3s; } #content { - margin: 2rem; + margin: 2rem; } .setting { - display: flex; - flex-direction: row; - justify-content: space-between; - padding: 0; - margin: 0.5rem 0; + display: flex; + flex-direction: row; + justify-content: space-between; + padding: 0; + margin: 0.5rem 0; } .settings-text { - margin-right: 2rem; - display: flex; + margin-right: 2rem; + display: flex; } /*** Toggle Switch styles ***/ .tgl-switch { - vertical-align: middle; - display: inline-block; + vertical-align: middle; + display: inline-block; } .tgl-switch .tgl { - display: none; + display: none; } .tgl, @@ -381,9 +465,9 @@ img#playButton { .tgl *, .tgl *:after, .tgl *:before, -.tgl + .tgl-slider { - -webkit-box-sizing: border-box; - box-sizing: border-box; +.tgl+.tgl-slider { + -webkit-box-sizing: border-box; + box-sizing: border-box; } .tgl::-moz-selection, @@ -392,8 +476,8 @@ img#playButton { .tgl *::-moz-selection, .tgl *:after::-moz-selection, .tgl *:before::-moz-selection, -.tgl + .tgl-slider::-moz-selection { - background: none; +.tgl+.tgl-slider::-moz-selection { + background: none; } .tgl::selection, @@ -402,244 +486,245 @@ img#playButton { .tgl *::selection, .tgl *:after::selection, .tgl *:before::selection, -.tgl + .tgl-slider::selection { - background: none; +.tgl+.tgl-slider::selection { + background: none; } -.tgl + .tgl-slider { - outline: 0; - display: block; - width: 40px; - height: 18px; - position: relative; - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; +.tgl+.tgl-slider { + outline: 0; + display: block; + width: 40px; + height: 18px; + position: relative; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } -.tgl + .tgl-slider:after, -.tgl + .tgl-slider:before { - position: relative; - display: block; - content: ""; - width: 50%; - height: 100%; +.tgl+.tgl-slider:after, +.tgl+.tgl-slider:before { + position: relative; + display: block; + content: ""; + width: 50%; + height: 100%; } -.tgl + .tgl-slider:after { - left: 0; +.tgl+.tgl-slider:after { + left: 0; } -.tgl + .tgl-slider:before { - display: none; +.tgl+.tgl-slider:before { + display: none; } -.tgl-flat + .tgl-slider { - padding: 2px; - -webkit-transition: all 0.2s ease; - transition: all 0.2s ease; - background: var(--colour6); - border: 3px solid var(--colour7); - border-radius: 2em; +.tgl-flat+.tgl-slider { + padding: 2px; + -webkit-transition: all .2s ease; + transition: all .2s ease; + background: var(--colour6); + border: 3px solid var(--colour7); + border-radius: 2em; } -.tgl-flat + .tgl-slider:after { - -webkit-transition: all 0.2s ease; - transition: all 0.2s ease; - background: var(--colour7); - content: ""; - border-radius: 1em; +.tgl-flat+.tgl-slider:after { + -webkit-transition: all .2s ease; + transition: all .2s ease; + background: var(--colour7); + content: ""; + border-radius: 1em; } -.tgl-flat:checked + .tgl-slider { - border: 3px solid var(--colour3); +.tgl-flat:checked+.tgl-slider { + border: 3px solid var(--colour3); } -.tgl-flat:checked + .tgl-slider:after { - left: 50%; - background: var(--colour3); +.tgl-flat:checked+.tgl-slider:after { + left: 50%; + background: var(--colour3); } .subtitle-text { - margin: 0 0 0 1rem; - color: var(--colour5); - position: relative; + margin: 0 0 0 1rem; + color: var(--colour5); + position: relative; } .form-group { - padding-top: 4px; - display: grid; - grid-template-columns: 50% 50%; - row-gap: 4px; - padding-right: 10px; - padding-left: 10px; + padding-top: 4px; + display: grid; + grid-template-columns: 50% 50%; + row-gap: 4px; + padding-right: 10px; + padding-left: 10px; } .form-group label { - color: var(--colour2); - vertical-align: middle; - font-weight: normal; + color: var(--colour2); + vertical-align: middle; + font-weight: normal; } #stats { - margin-left: 1rem; + margin-left: 1rem; } #LatencyStats { - margin-left: 1rem; + margin-left: 1rem; } #hiddenInput { - position: absolute; - left: -10%; - /* Although invisible, push off-screen to prevent user interaction. */ - width: 0px; - opacity: 0; + position: absolute; + left: -10%; + /* Although invisible, push off-screen to prevent user interaction. */ + width: 0px; + opacity: 0; } #editTextButton { - position: absolute; - height: 40px; - width: 40px; + position: absolute; + height: 40px; + width: 40px; } .form-group label { - margin-right: 2rem; - min-width: 75%; + margin-right: 2rem; + min-width: 75%; } input { - text-align: right; + text-align: right; } .warning { - box-sizing: border-box; - position: relative; - transform: scale(var(--ggs, 1)); - width: 20px; - height: 20px; - border: 2px solid; - border-radius: 40px; - display: none; + box-sizing: border-box; + position: relative; + transform: scale(var(--ggs, 1)); + width: 20px; + height: 20px; + border: 2px solid; + border-radius: 40px; + display: none; } .warning::after, .warning::before { - content: ""; - display: block; - box-sizing: border-box; - position: absolute; - border-radius: 3px; - width: 2px; - background: currentColor; - left: 7px; + content: ""; + display: block; + box-sizing: border-box; + position: absolute; + border-radius: 3px; + width: 2px; + background: currentColor; + left: 7px } .warning::after { - top: 2px; - height: 8px; + top: 2px; + height: 8px } .warning::before { - height: 2px; - bottom: 2px; + height: 2px; + bottom: 2px } /* Flat buttons */ input[type="button"] { - background-color: transparent; - color: var(--colour2); - font-family: "Montserrat"; - border: 3px solid var(--colour3); - border-radius: 1rem; - font-size: 0.75rem; - padding-left: 0.5rem; - padding-right: 0.5rem; + background-color: transparent; + color: var(--colour2); + font-family: 'Montserrat'; + border: 3px solid var(--colour3); + border-radius: 1rem; + font-size: 0.75rem; + padding-left: 0.5rem; + padding-right: 0.5rem; } input[type="button"]:hover { - background-color: var(--colour3); - transition: ease 0.3s; + background-color: var(--colour3); + transition: ease 0.3s; } input[type="button"]:active { - background-color: transparent; + background-color: transparent; } #encoder-params-submit, #webrtc-params-submit { - text-align: center; + text-align: center; } select, input[type="number"] { - background-color: var(--colour7); - color: var(--colour2); - border: 1px solid var(--colour6); - padding: 0.25rem; - font-family: "Montserrat"; - border-radius: 0.25rem; + background-color: var(--colour7); + color: var(--colour2); + border: 1px solid var(--colour6); + padding: 0.25rem; + font-family: 'Montserrat'; + border-radius: 0.25rem; } -input[type="number"]::-webkit-inner-spin-button { - margin-left: 0.5rem; +input[type=number]::-webkit-inner-spin-button { + margin-left: 0.5rem; } input[type="number"]:disabled { - padding-right: 0.5rem; - -moz-appearance: textfield; + padding-right: 0.5rem; + -moz-appearance: textfield; } -input[type="number"]:disabled::-webkit-inner-spin-button { - display: none; +input[type=number]:disabled::-webkit-inner-spin-button { + display: none; + } #settingsBtn, #statsBtn { - cursor: pointer; + cursor: pointer; } #streamingVideo { - pointer-events: all; + pointer-events: all; } embed { - border: none; - width: 100%; - height: 100%; + border: none; + width: 100%; + height: 100%; } g { - fill: var(--colour2); + fill: var(--colour2); } object { - pointer-events: none; + pointer-events: none; } #connectionStrength { - fill: var(--colour7); + fill: var(--colour7); } #minimize { - display: none; + display: none; } #afkOverlay { - z-index: 999; - background-color: rgba(30, 29, 34, 0.5); - display: inline-block; - height: 100vh; - width: 100vw; - line-height: 100vh; - text-align: center; - overflow: hidden; + z-index: 999; + background-color: rgba(30, 29, 34, 0.5); + display: inline-block; + height: 100vh; + width: 100vw; + line-height: 100vh; + text-align: center; + overflow: hidden; } #afkOverlay center { - display: inline-block; - line-height: 1.5; - height: 100vh; -} + display: inline-block; + line-height: 1.5; + height: 100vh; +} \ No newline at end of file diff --git a/WebServers/SignallingWebServer/fonts/Gilroy_Bold.woff b/WebServers/SignallingWebServer/fonts/Gilroy_Bold.woff new file mode 100644 index 0000000..c5bbebb Binary files /dev/null and b/WebServers/SignallingWebServer/fonts/Gilroy_Bold.woff differ diff --git a/WebServers/SignallingWebServer/fonts/Gilroy_Bold.woff2 b/WebServers/SignallingWebServer/fonts/Gilroy_Bold.woff2 new file mode 100644 index 0000000..bb8d73a Binary files /dev/null and b/WebServers/SignallingWebServer/fonts/Gilroy_Bold.woff2 differ diff --git a/WebServers/SignallingWebServer/fonts/Gilroy_Light.woff b/WebServers/SignallingWebServer/fonts/Gilroy_Light.woff new file mode 100644 index 0000000..3c8aca8 Binary files /dev/null and b/WebServers/SignallingWebServer/fonts/Gilroy_Light.woff differ diff --git a/WebServers/SignallingWebServer/fonts/Gilroy_Light.woff2 b/WebServers/SignallingWebServer/fonts/Gilroy_Light.woff2 new file mode 100644 index 0000000..bac74f7 Binary files /dev/null and b/WebServers/SignallingWebServer/fonts/Gilroy_Light.woff2 differ diff --git a/WebServers/SignallingWebServer/fonts/Gilroy_Medium.woff b/WebServers/SignallingWebServer/fonts/Gilroy_Medium.woff new file mode 100644 index 0000000..af869f6 Binary files /dev/null and b/WebServers/SignallingWebServer/fonts/Gilroy_Medium.woff differ diff --git a/WebServers/SignallingWebServer/fonts/Gilroy_Medium.woff2 b/WebServers/SignallingWebServer/fonts/Gilroy_Medium.woff2 new file mode 100644 index 0000000..dfaa5b6 Binary files /dev/null and b/WebServers/SignallingWebServer/fonts/Gilroy_Medium.woff2 differ diff --git a/WebServers/SignallingWebServer/fonts/Gilroy_Regular.woff b/WebServers/SignallingWebServer/fonts/Gilroy_Regular.woff new file mode 100644 index 0000000..d7ddc7e Binary files /dev/null and b/WebServers/SignallingWebServer/fonts/Gilroy_Regular.woff differ diff --git a/WebServers/SignallingWebServer/fonts/Gilroy_Regular.woff2 b/WebServers/SignallingWebServer/fonts/Gilroy_Regular.woff2 new file mode 100644 index 0000000..57b277d Binary files /dev/null and b/WebServers/SignallingWebServer/fonts/Gilroy_Regular.woff2 differ diff --git a/WebServers/SignallingWebServer/fonts/Gilroy_SemiBold.woff b/WebServers/SignallingWebServer/fonts/Gilroy_SemiBold.woff new file mode 100644 index 0000000..acdf98e Binary files /dev/null and b/WebServers/SignallingWebServer/fonts/Gilroy_SemiBold.woff differ diff --git a/WebServers/SignallingWebServer/fonts/Gilroy_SemiBold.woff2 b/WebServers/SignallingWebServer/fonts/Gilroy_SemiBold.woff2 new file mode 100644 index 0000000..9a1b0dc Binary files /dev/null and b/WebServers/SignallingWebServer/fonts/Gilroy_SemiBold.woff2 differ diff --git a/WebServers/SignallingWebServer/fonts/fonts.css b/WebServers/SignallingWebServer/fonts/fonts.css new file mode 100644 index 0000000..2e582f9 --- /dev/null +++ b/WebServers/SignallingWebServer/fonts/fonts.css @@ -0,0 +1,54 @@ +@font-face { + font-family: 'Inter'; + src: + url('./inter-v12-latin_cyrillic-regular.woff2') format('woff2'), + url('./inter-v12-latin_cyrillic-regular.woff') format('woff'); + font-weight: 400; + font-style: normal; +} + +@font-face { + font-family: 'Inter'; + src: + url('./inter-v12-latin_cyrillic-300.woff2') format('woff2'), + url('./inter-v12-latin_cyrillic-300.woff') format('woff'); + font-weight: 300; + font-style: normal; +} + +@font-face { + font-family: 'Inter'; + src: + url('./inter-v12-latin_cyrillic-500.woff2') format('woff2'), + url('./inter-v12-latin_cyrillic-500.woff') format('woff'); + font-weight: 500; + font-style: normal; +} + +@font-face { + font-family: 'Inter'; + src: + url('./inter-v12-latin_cyrillic-600.woff2') format('woff2'), + url('./inter-v12-latin_cyrillic-600.woff') format('woff'); + font-weight: 600; + font-style: normal; +} + +@font-face { + font-family: 'Inter'; + src: + url('./inter-v12-latin_cyrillic-700.woff2') format('woff2'), + url('./inter-v12-latin_cyrillic-700.woff') format('woff'); + font-weight: 700; + font-style: normal; +} + + +@font-face { + font-family: 'GilroyWebRegular'; + src: url('./Gilroy_Regular.woff'), + url('./Gilroy_Regular.woff2'); + font-weight: 400; + font-style: normal; + +} \ No newline at end of file diff --git a/WebServers/SignallingWebServer/fonts/inter-v12-latin_cyrillic-300.woff b/WebServers/SignallingWebServer/fonts/inter-v12-latin_cyrillic-300.woff new file mode 100644 index 0000000..dfbdbc5 Binary files /dev/null and b/WebServers/SignallingWebServer/fonts/inter-v12-latin_cyrillic-300.woff differ diff --git a/WebServers/SignallingWebServer/fonts/inter-v12-latin_cyrillic-300.woff2 b/WebServers/SignallingWebServer/fonts/inter-v12-latin_cyrillic-300.woff2 new file mode 100644 index 0000000..c34a22e Binary files /dev/null and b/WebServers/SignallingWebServer/fonts/inter-v12-latin_cyrillic-300.woff2 differ diff --git a/WebServers/SignallingWebServer/fonts/inter-v12-latin_cyrillic-500.woff b/WebServers/SignallingWebServer/fonts/inter-v12-latin_cyrillic-500.woff new file mode 100644 index 0000000..c66dbc7 Binary files /dev/null and b/WebServers/SignallingWebServer/fonts/inter-v12-latin_cyrillic-500.woff differ diff --git a/WebServers/SignallingWebServer/fonts/inter-v12-latin_cyrillic-500.woff2 b/WebServers/SignallingWebServer/fonts/inter-v12-latin_cyrillic-500.woff2 new file mode 100644 index 0000000..7538425 Binary files /dev/null and b/WebServers/SignallingWebServer/fonts/inter-v12-latin_cyrillic-500.woff2 differ diff --git a/WebServers/SignallingWebServer/fonts/inter-v12-latin_cyrillic-600.woff b/WebServers/SignallingWebServer/fonts/inter-v12-latin_cyrillic-600.woff new file mode 100644 index 0000000..d14fffe Binary files /dev/null and b/WebServers/SignallingWebServer/fonts/inter-v12-latin_cyrillic-600.woff differ diff --git a/WebServers/SignallingWebServer/fonts/inter-v12-latin_cyrillic-600.woff2 b/WebServers/SignallingWebServer/fonts/inter-v12-latin_cyrillic-600.woff2 new file mode 100644 index 0000000..3f47285 Binary files /dev/null and b/WebServers/SignallingWebServer/fonts/inter-v12-latin_cyrillic-600.woff2 differ diff --git a/WebServers/SignallingWebServer/fonts/inter-v12-latin_cyrillic-700.woff b/WebServers/SignallingWebServer/fonts/inter-v12-latin_cyrillic-700.woff new file mode 100644 index 0000000..f72a471 Binary files /dev/null and b/WebServers/SignallingWebServer/fonts/inter-v12-latin_cyrillic-700.woff differ diff --git a/WebServers/SignallingWebServer/fonts/inter-v12-latin_cyrillic-700.woff2 b/WebServers/SignallingWebServer/fonts/inter-v12-latin_cyrillic-700.woff2 new file mode 100644 index 0000000..60f0094 Binary files /dev/null and b/WebServers/SignallingWebServer/fonts/inter-v12-latin_cyrillic-700.woff2 differ diff --git a/WebServers/SignallingWebServer/fonts/inter-v12-latin_cyrillic-regular.woff b/WebServers/SignallingWebServer/fonts/inter-v12-latin_cyrillic-regular.woff new file mode 100644 index 0000000..87685eb Binary files /dev/null and b/WebServers/SignallingWebServer/fonts/inter-v12-latin_cyrillic-regular.woff differ diff --git a/WebServers/SignallingWebServer/fonts/inter-v12-latin_cyrillic-regular.woff2 b/WebServers/SignallingWebServer/fonts/inter-v12-latin_cyrillic-regular.woff2 new file mode 100644 index 0000000..daf5b02 Binary files /dev/null and b/WebServers/SignallingWebServer/fonts/inter-v12-latin_cyrillic-regular.woff2 differ diff --git a/WebServers/SignallingWebServer/images/Play.png b/WebServers/SignallingWebServer/images/Play.png index 0146c79..2d0ce2e 100644 Binary files a/WebServers/SignallingWebServer/images/Play.png and b/WebServers/SignallingWebServer/images/Play.png differ diff --git a/WebServers/SignallingWebServer/scripts/app.js b/WebServers/SignallingWebServer/scripts/app.js index 6981c8a..cd5ab2d 100644 --- a/WebServers/SignallingWebServer/scripts/app.js +++ b/WebServers/SignallingWebServer/scripts/app.js @@ -5,44 +5,39 @@ * TODO: Move these to seperate files once we introduce a bundler */ class TwoWayMap { - constructor(map = {}) { - this.map = map; - this.reverseMap = new Map(); - for (const key in map) { - const value = map[key]; - this.reverseMap[value] = key; + constructor(map = {}) { + this.map = map; + this.reverseMap = new Map(); + for (const key in map) { + const value = map[key]; + this.reverseMap[value] = key; + } } - } - getFromKey(key) { - return this.map[key]; - } - getFromValue(value) { - return this.reverseMap[value]; - } + getFromKey(key) { return this.map[key]; } + getFromValue(value) { return this.reverseMap[value]; } - add(key, value) { - this.map[key] = value; - this.reverseMap[value] = key; - } + add(key, value) { + this.map[key] = value; + this.reverseMap[value] = key; + } - remove(key, value) { - delete this.map[key]; - delete this.reverseMap[value]; - } + remove(key, value) { + delete this.map[key]; + delete this.reverseMap[value]; + } } /** * Frontend logic */ // Window events for a gamepad connecting -let haveEvents = "GamepadEvent" in window; -let haveWebkitEvents = "WebKitGamepadEvent" in window; +let haveEvents = 'GamepadEvent' in window; +let haveWebkitEvents = 'WebKitGamepadEvent' in window; let controllers = {}; -let rAF = - window.mozRequestAnimationFrame || - window.webkitRequestAnimationFrame || - window.requestAnimationFrame; +let rAF = window.mozRequestAnimationFrame || + window.webkitRequestAnimationFrame || + window.requestAnimationFrame; let webRtcPlayerObj = null; let print_stats = false; @@ -70,36 +65,36 @@ let isFullscreen = false; let isMuted = false; // A freeze frame is a still JPEG image shown instead of the video. let freezeFrame = { - receiving: false, - size: 0, - jpeg: undefined, - height: 0, - width: 0, - valid: false, + receiving: false, + size: 0, + jpeg: undefined, + height: 0, + width: 0, + valid: false }; let file = { - mimetype: "", - extension: "", - receiving: false, - size: 0, - data: [], - valid: false, - timestampStart: undefined, + mimetype: "", + extension: "", + receiving: false, + size: 0, + data: [], + valid: false, + timestampStart: undefined }; // Optionally detect if the user is not interacting (AFK) and disconnect them. let afk = { - enabled: false, // Set to true to enable the AFK system. - warnTimeout: 120, // The time to elapse before warning the user they are inactive. - closeTimeout: 10, // The time after the warning when we disconnect the user. + enabled: true, // Set to true to enable the AFK system. + warnTimeout: 120, // The time to elapse before warning the user they are inactive. + closeTimeout: 10, // The time after the warning when we disconnect the user. - active: false, // Whether the AFK system is currently looking for inactivity. - overlay: undefined, // The UI overlay warning the user that they are inactive. - warnTimer: undefined, // The timer which waits to show the inactivity warning overlay. - countdown: 0, // The inactivity warning overlay has a countdown to show time until disconnect. - countdownTimer: undefined, // The timer used to tick the seconds shown on the inactivity warning overlay. -}; + active: false, // Whether the AFK system is currently looking for inactivity. + overlay: undefined, // The UI overlay warning the user that they are inactive. + warnTimer: undefined, // The timer which waits to show the inactivity warning overlay. + countdown: 0, // The inactivity warning overlay has a countdown to show time until disconnect. + countdownTimer: undefined, // The timer used to tick the seconds shown on the inactivity warning overlay. +} // If the user focuses on a UE input widget then we show them a button to open // the on-screen keyboard. JavaScript security means we can only show the @@ -121,2152 +116,1728 @@ let toStreamerMessages = new TwoWayMap(); let fromStreamerMessages = new TwoWayMap(); const MessageDirection = { - // A message sent to the streamer. eg Key presses - // ie player -> streamer - ToStreamer: 0, + // A message sent to the streamer. eg Key presses + // ie player -> streamer + ToStreamer: 0, - // A message recevied from the streamer. eg Freeze frames - // ie streamer -> player - FromStreamer: 1, + // A message recevied from the streamer. eg Freeze frames + // ie streamer -> player + FromStreamer: 1 }; let toStreamerHandlers = new Map(); // toStreamerHandlers[message](args..) let fromStreamerHandlers = new Map(); // fromStreamerHandlers[message](args..) function populateDefaultProtocol() { - /* - * Control Messages. Range = 0..49. - */ - toStreamerMessages.add("IFrameRequest", { - id: 0, - byteLength: 0, - structure: [], - }); - toStreamerMessages.add("RequestQualityControl", { - id: 1, - byteLength: 0, - structure: [], - }); - toStreamerMessages.add("FpsRequest", { - id: 2, - byteLength: 0, - structure: [], - }); - toStreamerMessages.add("AverageBitrateRequest", { - id: 3, - byteLength: 0, - structure: [], - }); - toStreamerMessages.add("StartStreaming", { - id: 4, - byteLength: 0, - structure: [], - }); - toStreamerMessages.add("StopStreaming", { - id: 5, - byteLength: 0, - structure: [], - }); - toStreamerMessages.add("LatencyTest", { - id: 6, - byteLength: 0, - structure: [], - }); - toStreamerMessages.add("RequestInitialSettings", { - id: 7, - byteLength: 0, - structure: [], - }); - toStreamerMessages.add("TestEcho", { - id: 8, - byteLength: 0, - structure: [], - }); - /* - * Input Messages. Range = 50..89. - */ - // Generic Input Messages. Range = 50..59. - toStreamerMessages.add("UIInteraction", { - id: 50, - byteLength: 0, - structure: [], - }); - toStreamerMessages.add("Command", { - id: 51, - byteLength: 0, - structure: [], - }); - // Keyboard Input Message. Range = 60..69. - toStreamerMessages.add("KeyDown", { - id: 60, - byteLength: 2, - // keyCode isRepeat - structure: ["uint8", "uint8"], - }); - toStreamerMessages.add("KeyUp", { - id: 61, - byteLength: 1, - // keyCode - structure: ["uint8"], - }); - toStreamerMessages.add("KeyPress", { - id: 62, - byteLength: 2, - // charcode - structure: ["uint16"], - }); - // Mouse Input Messages. Range = 70..79. - toStreamerMessages.add("MouseEnter", { - id: 70, - byteLength: 0, - structure: [], - }); - toStreamerMessages.add("MouseLeave", { - id: 71, - byteLength: 0, - structure: [], - }); - toStreamerMessages.add("MouseDown", { - id: 72, - byteLength: 5, - // button x y - structure: ["uint8", "uint16", "uint16"], - }); - toStreamerMessages.add("MouseUp", { - id: 73, - byteLength: 5, - // button x y - structure: ["uint8", "uint16", "uint16"], - }); - toStreamerMessages.add("MouseMove", { - id: 74, - byteLength: 8, - // x y deltaX deltaY - structure: ["uint16", "uint16", "int16", "int16"], - }); - toStreamerMessages.add("MouseWheel", { - id: 75, - byteLength: 6, - // delta x y - structure: ["int16", "uint16", "uint16"], - }); - toStreamerMessages.add("MouseDouble", { - id: 76, - byteLength: 5, - // button x y - structure: ["uint8", "uint16", "uint16"], - }); - // Touch Input Messages. Range = 80..89. - toStreamerMessages.add("TouchStart", { - id: 80, - byteLength: 8, - // numtouches(1) x y idx force valid - structure: ["uint8", "uint16", "uint16", "uint8", "uint8", "uint8"], - }); - toStreamerMessages.add("TouchEnd", { - id: 81, - byteLength: 8, - // numtouches(1) x y idx force valid - structure: ["uint8", "uint16", "uint16", "uint8", "uint8", "uint8"], - }); - toStreamerMessages.add("TouchMove", { - id: 82, - byteLength: 8, - // numtouches(1) x y idx force valid - structure: ["uint8", "uint16", "uint16", "uint8", "uint8", "uint8"], - }); - // Gamepad Input Messages. Range = 90..99 - toStreamerMessages.add("GamepadButtonPressed", { - id: 90, - byteLength: 3, - // ctrlerId button isRepeat - structure: ["uint8", "uint8", "uint8"], - }); - toStreamerMessages.add("GamepadButtonReleased", { - id: 91, - byteLength: 3, - // ctrlerId button isRepeat(0) - structure: ["uint8", "uint8", "uint8"], - }); - toStreamerMessages.add("GamepadAnalog", { - id: 92, - byteLength: 10, - // ctrlerId button analogValue - structure: ["uint8", "uint8", "double"], - }); + /* + * Control Messages. Range = 0..49. + */ + toStreamerMessages.add("IFrameRequest", { + "id": 0, + "byteLength": 0, + "structure": [] + }); + toStreamerMessages.add("RequestQualityControl", { + "id": 1, + "byteLength": 0, + "structure": [] + }); + toStreamerMessages.add("FpsRequest", { + "id": 2, + "byteLength": 0, + "structure": [] + }); + toStreamerMessages.add("AverageBitrateRequest", { + "id": 3, + "byteLength": 0, + "structure": [] + }); + toStreamerMessages.add("StartStreaming", { + "id": 4, + "byteLength": 0, + "structure": [] + }); + toStreamerMessages.add("StopStreaming", { + "id": 5, + "byteLength": 0, + "structure": [] + }); + toStreamerMessages.add("LatencyTest", { + "id": 6, + "byteLength": 0, + "structure": [] + }); + toStreamerMessages.add("RequestInitialSettings", { + "id": 7, + "byteLength": 0, + "structure": [] + }); + toStreamerMessages.add("TestEcho", { + "id": 8, + "byteLength": 0, + "structure": [] + }); + /* + * Input Messages. Range = 50..89. + */ + // Generic Input Messages. Range = 50..59. + toStreamerMessages.add("UIInteraction", { + "id": 50, + "byteLength": 0, + "structure": [] + }); + toStreamerMessages.add("Command", { + "id": 51, + "byteLength": 0, + "structure": [] + }); + // Keyboard Input Message. Range = 60..69. + toStreamerMessages.add("KeyDown", { + "id": 60, + "byteLength": 2, + // keyCode isRepeat + "structure": ["uint8", "uint8"] + }); + toStreamerMessages.add("KeyUp", { + "id": 61, + "byteLength": 1, + // keyCode + "structure": ["uint8"] + }); + toStreamerMessages.add("KeyPress", { + "id": 62, + "byteLength": 2, + // charcode + "structure": ["uint16"] + }); + // Mouse Input Messages. Range = 70..79. + toStreamerMessages.add("MouseEnter", { + "id": 70, + "byteLength": 0, + "structure": [] + }); + toStreamerMessages.add("MouseLeave", { + "id": 71, + "byteLength": 0, + "structure": [] + }); + toStreamerMessages.add("MouseDown", { + "id": 72, + "byteLength": 5, + // button x y + "structure": ["uint8", "uint16", "uint16"] + }); + toStreamerMessages.add("MouseUp", { + "id": 73, + "byteLength": 5, + // button x y + "structure": ["uint8", "uint16", "uint16"] + }); + toStreamerMessages.add("MouseMove", { + "id": 74, + "byteLength": 8, + // x y deltaX deltaY + "structure": ["uint16", "uint16", "int16", "int16"] + }); + toStreamerMessages.add("MouseWheel", { + "id": 75, + "byteLength": 6, + // delta x y + "structure": ["int16", "uint16", "uint16"] + }); + toStreamerMessages.add("MouseDouble", { + "id": 76, + "byteLength": 5, + // button x y + "structure": ["uint8", "uint16", "uint16"] + }); + // Touch Input Messages. Range = 80..89. + toStreamerMessages.add("TouchStart", { + "id": 80, + "byteLength": 8, + // numtouches(1) x y idx force valid + "structure": ["uint8", "uint16", "uint16", "uint8", "uint8", "uint8"] + }); + toStreamerMessages.add("TouchEnd", { + "id": 81, + "byteLength": 8, + // numtouches(1) x y idx force valid + "structure": ["uint8", "uint16", "uint16", "uint8", "uint8", "uint8"] + }); + toStreamerMessages.add("TouchMove", { + "id": 82, + "byteLength": 8, + // numtouches(1) x y idx force valid + "structure": ["uint8", "uint16", "uint16", "uint8", "uint8", "uint8"] + }); + // Gamepad Input Messages. Range = 90..99 + toStreamerMessages.add("GamepadButtonPressed", { + "id": 90, + "byteLength": 3, + // ctrlerId button isRepeat + "structure": ["uint8", "uint8", "uint8"] + }); + toStreamerMessages.add("GamepadButtonReleased", { + "id": 91, + "byteLength": 3, + // ctrlerId button isRepeat(0) + "structure": ["uint8", "uint8", "uint8"] + }); + toStreamerMessages.add("GamepadAnalog", { + "id": 92, + "byteLength": 10, + // ctrlerId button analogValue + "structure": ["uint8", "uint8", "double"] + }); - fromStreamerMessages.add("QualityControlOwnership", 0); - fromStreamerMessages.add("Response", 1); - fromStreamerMessages.add("Command", 2); - fromStreamerMessages.add("FreezeFrame", 3); - fromStreamerMessages.add("UnfreezeFrame", 4); - fromStreamerMessages.add("VideoEncoderAvgQP", 5); - fromStreamerMessages.add("LatencyTest", 6); - fromStreamerMessages.add("InitialSettings", 7); - fromStreamerMessages.add("FileExtension", 8); - fromStreamerMessages.add("FileMimeType", 9); - fromStreamerMessages.add("FileContents", 10); - fromStreamerMessages.add("TestEcho", 11); - fromStreamerMessages.add("InputControlOwnership", 12); - fromStreamerMessages.add("Protocol", 255); + fromStreamerMessages.add("QualityControlOwnership", 0); + fromStreamerMessages.add("Response", 1); + fromStreamerMessages.add("Command", 2); + fromStreamerMessages.add("FreezeFrame", 3); + fromStreamerMessages.add("UnfreezeFrame", 4); + fromStreamerMessages.add("VideoEncoderAvgQP", 5); + fromStreamerMessages.add("LatencyTest", 6); + fromStreamerMessages.add("InitialSettings", 7); + fromStreamerMessages.add("FileExtension", 8); + fromStreamerMessages.add("FileMimeType", 9); + fromStreamerMessages.add("FileContents", 10); + fromStreamerMessages.add("TestEcho", 11); + fromStreamerMessages.add("InputControlOwnership", 12); + fromStreamerMessages.add("Protocol", 255); } function registerMessageHandlers() { - registerMessageHandler( - MessageDirection.FromStreamer, - "QualityControlOwnership", - onQualityControlOwnership - ); - registerMessageHandler(MessageDirection.FromStreamer, "Response", onResponse); - registerMessageHandler(MessageDirection.FromStreamer, "Command", onCommand); - registerMessageHandler( - MessageDirection.FromStreamer, - "FreezeFrame", - onFreezeFrameMessage - ); - registerMessageHandler( - MessageDirection.FromStreamer, - "UnfreezeFrame", - invalidateFreezeFrameOverlay - ); - registerMessageHandler( - MessageDirection.FromStreamer, - "VideoEncoderAvgQP", - onVideoEncoderAvgQP - ); - registerMessageHandler( - MessageDirection.FromStreamer, - "LatencyTest", - onLatencyTestMessage - ); - registerMessageHandler( - MessageDirection.FromStreamer, - "InitialSettings", - onInitialSettings - ); - registerMessageHandler( - MessageDirection.FromStreamer, - "FileExtension", - onFileExtension - ); - registerMessageHandler( - MessageDirection.FromStreamer, - "FileMimeType", - onFileMimeType - ); - registerMessageHandler( - MessageDirection.FromStreamer, - "FileContents", - onFileContents - ); - registerMessageHandler(MessageDirection.FromStreamer, "TestEcho", () => { - /* Do nothing */ - }); - registerMessageHandler( - MessageDirection.FromStreamer, - "InputControlOwnership", - onInputControlOwnership - ); - registerMessageHandler( - MessageDirection.FromStreamer, - "Protocol", - onProtocolMessage - ); + registerMessageHandler(MessageDirection.FromStreamer, "QualityControlOwnership", onQualityControlOwnership); + registerMessageHandler(MessageDirection.FromStreamer, "Response", onResponse); + registerMessageHandler(MessageDirection.FromStreamer, "Command", onCommand); + registerMessageHandler(MessageDirection.FromStreamer, "FreezeFrame", onFreezeFrameMessage); + registerMessageHandler(MessageDirection.FromStreamer, "UnfreezeFrame", invalidateFreezeFrameOverlay); + registerMessageHandler(MessageDirection.FromStreamer, "VideoEncoderAvgQP", onVideoEncoderAvgQP); + registerMessageHandler(MessageDirection.FromStreamer, "LatencyTest", onLatencyTestMessage); + registerMessageHandler(MessageDirection.FromStreamer, "InitialSettings", onInitialSettings); + registerMessageHandler(MessageDirection.FromStreamer, "FileExtension", onFileExtension); + registerMessageHandler(MessageDirection.FromStreamer, "FileMimeType", onFileMimeType); + registerMessageHandler(MessageDirection.FromStreamer, "FileContents", onFileContents); + registerMessageHandler(MessageDirection.FromStreamer, "TestEcho", () => {/* Do nothing */ }); + registerMessageHandler(MessageDirection.FromStreamer, "InputControlOwnership", onInputControlOwnership); + registerMessageHandler(MessageDirection.FromStreamer, "Protocol", onProtocolMessage); - registerMessageHandler( - MessageDirection.ToStreamer, - "IFrameRequest", - sendMessageToStreamer - ); - registerMessageHandler( - MessageDirection.ToStreamer, - "RequestQualityControl", - sendMessageToStreamer - ); - registerMessageHandler( - MessageDirection.ToStreamer, - "FpsRequest", - sendMessageToStreamer - ); - registerMessageHandler( - MessageDirection.ToStreamer, - "AverageBitrateRequest", - sendMessageToStreamer - ); - registerMessageHandler( - MessageDirection.ToStreamer, - "StartStreaming", - sendMessageToStreamer - ); - registerMessageHandler( - MessageDirection.ToStreamer, - "StopStreaming", - sendMessageToStreamer - ); - registerMessageHandler( - MessageDirection.ToStreamer, - "LatencyTest", - sendMessageToStreamer - ); - registerMessageHandler( - MessageDirection.ToStreamer, - "RequestInitialSettings", - sendMessageToStreamer - ); - registerMessageHandler(MessageDirection.ToStreamer, "TestEcho", () => { - /* Do nothing */ - }); - registerMessageHandler( - MessageDirection.ToStreamer, - "UIInteraction", - emitUIInteraction - ); - registerMessageHandler(MessageDirection.ToStreamer, "Command", emitCommand); - registerMessageHandler( - MessageDirection.ToStreamer, - "KeyDown", - sendMessageToStreamer - ); - registerMessageHandler( - MessageDirection.ToStreamer, - "KeyUp", - sendMessageToStreamer - ); - registerMessageHandler( - MessageDirection.ToStreamer, - "KeyPress", - sendMessageToStreamer - ); - registerMessageHandler( - MessageDirection.ToStreamer, - "MouseEnter", - sendMessageToStreamer - ); - registerMessageHandler( - MessageDirection.ToStreamer, - "MouseLeave", - sendMessageToStreamer - ); - registerMessageHandler( - MessageDirection.ToStreamer, - "MouseDown", - sendMessageToStreamer - ); - registerMessageHandler( - MessageDirection.ToStreamer, - "MouseUp", - sendMessageToStreamer - ); - registerMessageHandler( - MessageDirection.ToStreamer, - "MouseMove", - sendMessageToStreamer - ); - registerMessageHandler( - MessageDirection.ToStreamer, - "MouseWheel", - sendMessageToStreamer - ); - registerMessageHandler( - MessageDirection.ToStreamer, - "MouseDouble", - sendMessageToStreamer - ); - registerMessageHandler( - MessageDirection.ToStreamer, - "TouchStart", - sendMessageToStreamer - ); - registerMessageHandler( - MessageDirection.ToStreamer, - "TouchEnd", - sendMessageToStreamer - ); - registerMessageHandler( - MessageDirection.ToStreamer, - "TouchMove", - sendMessageToStreamer - ); - registerMessageHandler( - MessageDirection.ToStreamer, - "GamepadButtonPressed", - sendMessageToStreamer - ); - registerMessageHandler( - MessageDirection.ToStreamer, - "GamepadButtonReleased", - sendMessageToStreamer - ); - registerMessageHandler( - MessageDirection.ToStreamer, - "GamepadAnalog", - sendMessageToStreamer - ); + registerMessageHandler(MessageDirection.ToStreamer, "IFrameRequest", sendMessageToStreamer); + registerMessageHandler(MessageDirection.ToStreamer, "RequestQualityControl", sendMessageToStreamer); + registerMessageHandler(MessageDirection.ToStreamer, "FpsRequest", sendMessageToStreamer); + registerMessageHandler(MessageDirection.ToStreamer, "AverageBitrateRequest", sendMessageToStreamer); + registerMessageHandler(MessageDirection.ToStreamer, "StartStreaming", sendMessageToStreamer); + registerMessageHandler(MessageDirection.ToStreamer, "StopStreaming", sendMessageToStreamer); + registerMessageHandler(MessageDirection.ToStreamer, "LatencyTest", sendMessageToStreamer); + registerMessageHandler(MessageDirection.ToStreamer, "RequestInitialSettings", sendMessageToStreamer); + registerMessageHandler(MessageDirection.ToStreamer, "TestEcho", () => { /* Do nothing */ }); + registerMessageHandler(MessageDirection.ToStreamer, "UIInteraction", emitUIInteraction); + registerMessageHandler(MessageDirection.ToStreamer, "Command", emitCommand); + registerMessageHandler(MessageDirection.ToStreamer, "KeyDown", sendMessageToStreamer); + registerMessageHandler(MessageDirection.ToStreamer, "KeyUp", sendMessageToStreamer); + registerMessageHandler(MessageDirection.ToStreamer, "KeyPress", sendMessageToStreamer); + registerMessageHandler(MessageDirection.ToStreamer, "MouseEnter", sendMessageToStreamer); + registerMessageHandler(MessageDirection.ToStreamer, "MouseLeave", sendMessageToStreamer); + registerMessageHandler(MessageDirection.ToStreamer, "MouseDown", sendMessageToStreamer); + registerMessageHandler(MessageDirection.ToStreamer, "MouseUp", sendMessageToStreamer); + registerMessageHandler(MessageDirection.ToStreamer, "MouseMove", sendMessageToStreamer); + registerMessageHandler(MessageDirection.ToStreamer, "MouseWheel", sendMessageToStreamer); + registerMessageHandler(MessageDirection.ToStreamer, "MouseDouble", sendMessageToStreamer); + registerMessageHandler(MessageDirection.ToStreamer, "TouchStart", sendMessageToStreamer); + registerMessageHandler(MessageDirection.ToStreamer, "TouchEnd", sendMessageToStreamer); + registerMessageHandler(MessageDirection.ToStreamer, "TouchMove", sendMessageToStreamer); + registerMessageHandler(MessageDirection.ToStreamer, "GamepadButtonPressed", sendMessageToStreamer); + registerMessageHandler(MessageDirection.ToStreamer, "GamepadButtonReleased", sendMessageToStreamer); + registerMessageHandler(MessageDirection.ToStreamer, "GamepadAnalog", sendMessageToStreamer); } function registerMessageHandler(messageDirection, messageType, messageHandler) { - switch (messageDirection) { - case MessageDirection.ToStreamer: - toStreamerHandlers[messageType] = messageHandler; - break; - case MessageDirection.FromStreamer: - fromStreamerHandlers[messageType] = messageHandler; - break; - default: - console.log(`Unknown message direction ${messageDirection}`); - } + switch (messageDirection) { + case MessageDirection.ToStreamer: + toStreamerHandlers[messageType] = messageHandler; + break; + case MessageDirection.FromStreamer: + fromStreamerHandlers[messageType] = messageHandler; + break; + default: + console.log(`Unknown message direction ${messageDirection}`); + } } function onQualityControlOwnership(data) { - let view = new Uint8Array(data); - let ownership = view[1] === 0 ? false : true; - console.log( - "Received quality controller message, will control quality: " + ownership - ); - qualityController = ownership; - // If we own the quality control, we can't relinquish it. We only lose - // quality control when another peer asks for it - if (qualityControlOwnershipCheckBox !== null) { - qualityControlOwnershipCheckBox.disabled = ownership; - qualityControlOwnershipCheckBox.checked = ownership; - } + let view = new Uint8Array(data); + let ownership = view[1] === 0 ? false : true; + console.log("Received quality controller message, will control quality: " + ownership); + qualityController = ownership; + // If we own the quality control, we can't relinquish it. We only lose + // quality control when another peer asks for it + if (qualityControlOwnershipCheckBox !== null) { + qualityControlOwnershipCheckBox.disabled = ownership; + qualityControlOwnershipCheckBox.checked = ownership; + } } function onResponse(data) { - let response = new TextDecoder("utf-16").decode(data.slice(1)); - for (let listener of responseEventListeners.values()) { - listener(response); - } + let response = new TextDecoder("utf-16").decode(data.slice(1)); + for (let listener of responseEventListeners.values()) { + listener(response); + } } function onCommand(data) { - let commandAsString = new TextDecoder("utf-16").decode(data.slice(1)); - console.log(commandAsString); - let command = JSON.parse(commandAsString); - if (command.command === "onScreenKeyboard") { - showOnScreenKeyboard(command); - } + let commandAsString = new TextDecoder("utf-16").decode(data.slice(1)); + console.log(commandAsString); + let command = JSON.parse(commandAsString); + if (command.command === 'onScreenKeyboard') { + showOnScreenKeyboard(command); + } } function onFreezeFrameMessage(data) { - let view = new Uint8Array(data); - processFreezeFrameMessage(view); + let view = new Uint8Array(data); + processFreezeFrameMessage(view); } function onVideoEncoderAvgQP(data) { - VideoEncoderQP = new TextDecoder("utf-16").decode(data.slice(1)); + VideoEncoderQP = new TextDecoder("utf-16").decode(data.slice(1)); } function onLatencyTestMessage(data) { - let latencyTimingsAsString = new TextDecoder("utf-16").decode(data.slice(1)); - console.log("Got latency timings from UE."); - console.log(latencyTimingsAsString); - let latencyTimingsFromUE = JSON.parse(latencyTimingsAsString); - if (webRtcPlayerObj) { - webRtcPlayerObj.latencyTestTimings.SetUETimings(latencyTimingsFromUE); - } + let latencyTimingsAsString = new TextDecoder("utf-16").decode(data.slice(1)); + console.log("Got latency timings from UE."); + console.log(latencyTimingsAsString); + let latencyTimingsFromUE = JSON.parse(latencyTimingsAsString); + if (webRtcPlayerObj) { + webRtcPlayerObj.latencyTestTimings.SetUETimings(latencyTimingsFromUE); + } } function onInitialSettings(data) { - let settingsString = new TextDecoder("utf-16").decode(data.slice(1)); - let settingsJSON = JSON.parse(settingsString); + let settingsString = new TextDecoder("utf-16").decode(data.slice(1)); + let settingsJSON = JSON.parse(settingsString); - if (settingsJSON.PixelStreaming) { - let allowConsoleCommands = - settingsJSON.PixelStreaming.AllowPixelStreamingCommands; - if (allowConsoleCommands === false) { - console.warn( - "-AllowPixelStreamingCommands=false, sending arbitray console commands from browser to UE is disabled." - ); + if (settingsJSON.PixelStreaming) { + let allowConsoleCommands = settingsJSON.PixelStreaming.AllowPixelStreamingCommands; + if (allowConsoleCommands === false) { + console.warn("-AllowPixelStreamingCommands=false, sending arbitray console commands from browser to UE is disabled."); + } + let disableLatencyTest = settingsJSON.PixelStreaming.DisableLatencyTest; + if (disableLatencyTest) { + document.getElementById("test-latency-button").disabled = true; + document.getElementById("test-latency-button").title = "Disabled by -PixelStreamingDisableLatencyTester=true"; + console.warn("-PixelStreamingDisableLatencyTester=true, requesting latency report from the the browser to UE is disabled."); + } } - let disableLatencyTest = settingsJSON.PixelStreaming.DisableLatencyTest; - if (disableLatencyTest) { - document.getElementById("test-latency-button").disabled = true; - document.getElementById("test-latency-button").title = - "Disabled by -PixelStreamingDisableLatencyTester=true"; - console.warn( - "-PixelStreamingDisableLatencyTester=true, requesting latency report from the the browser to UE is disabled." - ); + if (settingsJSON.Encoder) { + document.getElementById('encoder-min-qp-text').value = settingsJSON.Encoder.MinQP; + document.getElementById('encoder-max-qp-text').value = settingsJSON.Encoder.MaxQP; + } + if (settingsJSON.WebRTC) { + document.getElementById("webrtc-fps-text").value = settingsJSON.WebRTC.FPS; + // reminder bitrates are sent in bps but displayed in kbps + document.getElementById("webrtc-min-bitrate-text").value = settingsJSON.WebRTC.MinBitrate / 1000; + document.getElementById("webrtc-max-bitrate-text").value = settingsJSON.WebRTC.MaxBitrate / 1000; } - } - if (settingsJSON.Encoder) { - document.getElementById("encoder-min-qp-text").value = - settingsJSON.Encoder.MinQP; - document.getElementById("encoder-max-qp-text").value = - settingsJSON.Encoder.MaxQP; - } - if (settingsJSON.WebRTC) { - document.getElementById("webrtc-fps-text").value = settingsJSON.WebRTC.FPS; - // reminder bitrates are sent in bps but displayed in kbps - document.getElementById("webrtc-min-bitrate-text").value = - settingsJSON.WebRTC.MinBitrate / 1000; - document.getElementById("webrtc-max-bitrate-text").value = - settingsJSON.WebRTC.MaxBitrate / 1000; - } } function onFileExtension(data) { - let view = new Uint8Array(data); - processFileExtension(view); + let view = new Uint8Array(data); + processFileExtension(view); } function onFileMimeType(data) { - let view = new Uint8Array(data); - processFileMimeType(view); + let view = new Uint8Array(data); + processFileMimeType(view); } function onFileContents(data) { - let view = new Uint8Array(data); - processFileContents(view); + let view = new Uint8Array(data); + processFileContents(view); } function onInputControlOwnership(data) { - let view = new Uint8Array(data); - let ownership = view[1] === 0 ? false : true; - console.log( - "Received input controller message - will your input control the stream: " + - ownership - ); - inputController = ownership; + let view = new Uint8Array(data); + let ownership = view[1] === 0 ? false : true; + console.log("Received input controller message - will your input control the stream: " + ownership); + inputController = ownership; } function onProtocolMessage(data) { - try { - let protocolString = new TextDecoder("utf-16").decode(data.slice(1)); - let protocolJSON = JSON.parse(protocolString); - if (!protocolJSON.hasOwnProperty("Direction")) { - throw new Error( - "Malformed protocol received. Ensure the protocol message contains a direction" - ); - } - let direction = protocolJSON.Direction; - delete protocolJSON.Direction; - console.log( - `Received new ${ - direction == MessageDirection.FromStreamer - ? "FromStreamer" - : "ToStreamer" - } protocol. Updating existing protocol...` - ); - Object.keys(protocolJSON).forEach((messageType) => { - let message = protocolJSON[messageType]; - switch (direction) { - case MessageDirection.ToStreamer: - // Check that the message contains all the relevant params - if ( - !message.hasOwnProperty("id") || - !message.hasOwnProperty("byteLength") - ) { - console.error(`ToStreamer->${messageType} protocol definition was malformed as it didn't contain at least an id and a byteLength\n - Definition was: ${JSON.stringify( - message, - null, - 2 - )}`); - // return in a forEach is equivalent to a continue in a normal for loop - return; - } - if (message.byteLength > 0 && !message.hasOwnProperty("structure")) { - // If we specify a bytelength, will must have a corresponding structure - console.error( - `ToStreamer->${messageType} protocol definition was malformed as it specified a byteLength but no accompanying structure` - ); - // return in a forEach is equivalent to a continue in a normal for loop - return; - } + try { + let protocolString = new TextDecoder("utf-16").decode(data.slice(1)); + let protocolJSON = JSON.parse(protocolString); + if (!protocolJSON.hasOwnProperty("Direction")) { + throw new Error('Malformed protocol received. Ensure the protocol message contains a direction'); + } + let direction = protocolJSON.Direction; + delete protocolJSON.Direction; + console.log(`Received new ${direction == MessageDirection.FromStreamer ? "FromStreamer" : "ToStreamer"} protocol. Updating existing protocol...`); + Object.keys(protocolJSON).forEach((messageType) => { + let message = protocolJSON[messageType]; + switch (direction) { + case MessageDirection.ToStreamer: + // Check that the message contains all the relevant params + if (!message.hasOwnProperty("id") || !message.hasOwnProperty("byteLength")) { + console.error(`ToStreamer->${messageType} protocol definition was malformed as it didn't contain at least an id and a byteLength\n + Definition was: ${JSON.stringify(message, null, 2)}`); + // return in a forEach is equivalent to a continue in a normal for loop + return; + } + if (message.byteLength > 0 && !message.hasOwnProperty("structure")) { + // If we specify a bytelength, will must have a corresponding structure + console.error(`ToStreamer->${messageType} protocol definition was malformed as it specified a byteLength but no accompanying structure`); + // return in a forEach is equivalent to a continue in a normal for loop + return; + } - if (toStreamerHandlers[messageType]) { - // If we've registered a handler for this message type we can add it to our supported messages. ie registerMessageHandler(...) - toStreamerMessages.add(messageType, message); - } else { - console.error( - `There was no registered handler for "${messageType}" - try adding one using registerMessageHandler(MessageDirection.ToStreamer, "${messageType}", myHandler)` - ); - } - break; - case MessageDirection.FromStreamer: - // Check that the message contains all the relevant params - if (!message.hasOwnProperty("id")) { - console.error(`FromStreamer->${messageType} protocol definition was malformed as it didn't contain at least an id\n + if (toStreamerHandlers[messageType]) { + // If we've registered a handler for this message type we can add it to our supported messages. ie registerMessageHandler(...) + toStreamerMessages.add(messageType, message); + } else { + console.error(`There was no registered handler for "${messageType}" - try adding one using registerMessageHandler(MessageDirection.ToStreamer, "${messageType}", myHandler)`); + } + break; + case MessageDirection.FromStreamer: + // Check that the message contains all the relevant params + if (!message.hasOwnProperty("id")) { + console.error(`FromStreamer->${messageType} protocol definition was malformed as it didn't contain at least an id\n Definition was: ${JSON.stringify(message, null, 2)}`); - // return in a forEach is equivalent to a continue in a normal for loop - return; - } - if (fromStreamerHandlers[messageType]) { - // If we've registered a handler for this message type. ie registerMessageHandler(...) - fromStreamerMessages.add(messageType, message.id); - } else { - console.error( - `There was no registered handler for "${message}" - try adding one using registerMessageHandler(MessageDirection.FromStreamer, "${messageType}", myHandler)` - ); - } - break; - default: - throw new Error(`Unknown direction: ${direction}`); - } - }); + // return in a forEach is equivalent to a continue in a normal for loop + return; + } + if (fromStreamerHandlers[messageType]) { + // If we've registered a handler for this message type. ie registerMessageHandler(...) + fromStreamerMessages.add(messageType, message.id); + } else { + console.error(`There was no registered handler for "${message}" - try adding one using registerMessageHandler(MessageDirection.FromStreamer, "${messageType}", myHandler)`); + } + break; + default: + throw new Error(`Unknown direction: ${direction}`); + } + }); - // Once the protocol has been received, we can send our control messages - requestInitialSettings(); - requestQualityControl(); - } catch (e) { - console.log(e); - } + // Once the protocol has been received, we can send our control messages + requestInitialSettings(); + requestQualityControl(); + } catch (e) { + console.log(e); + } } // https://w3c.github.io/gamepad/#remapping const gamepadLayout = { - // Buttons - RightClusterBottomButton: 0, - RightClusterRightButton: 1, - RightClusterLeftButton: 2, - RightClusterTopButton: 3, - LeftShoulder: 4, - RightShoulder: 5, - LeftTrigger: 6, - RightTrigger: 7, - SelectOrBack: 8, - StartOrForward: 9, - LeftAnalogPress: 10, - RightAnalogPress: 11, - LeftClusterTopButton: 12, - LeftClusterBottomButton: 13, - LeftClusterLeftButton: 14, - LeftClusterRightButton: 15, - CentreButton: 16, - // Axes - LeftStickHorizontal: 0, - LeftStickVertical: 1, - RightStickHorizontal: 2, - RightStickVertical: 3, + // Buttons + RightClusterBottomButton: 0, + RightClusterRightButton: 1, + RightClusterLeftButton: 2, + RightClusterTopButton: 3, + LeftShoulder: 4, + RightShoulder: 5, + LeftTrigger: 6, + RightTrigger: 7, + SelectOrBack: 8, + StartOrForward: 9, + LeftAnalogPress: 10, + RightAnalogPress: 11, + LeftClusterTopButton: 12, + LeftClusterBottomButton: 13, + LeftClusterLeftButton: 14, + LeftClusterRightButton: 15, + CentreButton: 16, + // Axes + LeftStickHorizontal: 0, + LeftStickVertical: 1, + RightStickHorizontal: 2, + RightStickVertical: 3 }; function scanGamepads() { - let gamepads = navigator.getGamepads - ? navigator.getGamepads() - : navigator.webkitGetGamepads - ? navigator.webkitGetGamepads() - : []; - for (let i = 0; i < gamepads.length; i++) { - if (gamepads[i] && gamepads[i].index in controllers) { - controllers[gamepads[i].index].currentState = gamepads[i]; + let gamepads = navigator.getGamepads ? navigator.getGamepads() : (navigator.webkitGetGamepads ? navigator.webkitGetGamepads() : []); + for (let i = 0; i < gamepads.length; i++) { + if (gamepads[i] && (gamepads[i].index in controllers)) { + controllers[gamepads[i].index].currentState = gamepads[i]; + } } - } } function updateStatus() { - scanGamepads(); - // Iterate over multiple controllers in the case the mutiple gamepads are connected - for (let j in controllers) { - let controller = controllers[j]; - let currentState = controller.currentState; - let prevState = controller.prevState; - // Iterate over buttons - for (let i = 0; i < currentState.buttons.length; i++) { - let currButton = currentState.buttons[i]; - let prevButton = prevState.buttons[i]; - if (currButton.pressed) { - // press - if (i == gamepadLayout.LeftTrigger) { - // UEs left analog has a button index of 5 - toStreamerHandlers.GamepadAnalog("GamepadAnalog", [ - j, - 5, - currButton.value, - ]); - } else if (i == gamepadLayout.RightTrigger) { - // UEs right analog has a button index of 6 - toStreamerHandlers.GamepadAnalog("GamepadAnalog", [ - j, - 6, - currButton.value, - ]); - } else { - toStreamerHandlers.GamepadButtonPressed("GamepadButtonPressed", [ - j, - i, - prevButton.pressed, - ]); + scanGamepads(); + // Iterate over multiple controllers in the case the mutiple gamepads are connected + for (let j in controllers) { + let controller = controllers[j]; + let currentState = controller.currentState; + let prevState = controller.prevState; + // Iterate over buttons + for (let i = 0; i < currentState.buttons.length; i++) { + let currButton = currentState.buttons[i]; + let prevButton = prevState.buttons[i]; + if (currButton.pressed) { + // press + if (i == gamepadLayout.LeftTrigger) { + // UEs left analog has a button index of 5 + toStreamerHandlers.GamepadAnalog("GamepadAnalog", [j, 5, currButton.value]); + } else if (i == gamepadLayout.RightTrigger) { + // UEs right analog has a button index of 6 + toStreamerHandlers.GamepadAnalog("GamepadAnalog", [j, 6, currButton.value]); + } else { + toStreamerHandlers.GamepadButtonPressed("GamepadButtonPressed", [j, i, prevButton.pressed]); + } + } else if (!currButton.pressed && prevButton.pressed) { + // release + if (i == gamepadLayout.LeftTrigger) { + // UEs left analog has a button index of 5 + toStreamerHandlers.GamepadAnalog("GamepadAnalog", [j, 5, 0]); + } else if (i == gamepadLayout.RightTrigger) { + // UEs right analog has a button index of 6 + toStreamerHandlers.GamepadAnalog("GamepadAnalog", [j, 6, 0]); + } else { + toStreamerHandlers.GamepadButtonReleased("GamepadButtonReleased", [j, i]); + } + } } - } else if (!currButton.pressed && prevButton.pressed) { - // release - if (i == gamepadLayout.LeftTrigger) { - // UEs left analog has a button index of 5 - toStreamerHandlers.GamepadAnalog("GamepadAnalog", [j, 5, 0]); - } else if (i == gamepadLayout.RightTrigger) { - // UEs right analog has a button index of 6 - toStreamerHandlers.GamepadAnalog("GamepadAnalog", [j, 6, 0]); - } else { - toStreamerHandlers.GamepadButtonReleased("GamepadButtonReleased", [ - j, - i, - ]); + // Iterate over gamepad axes (we will increment in lots of 2 as there is 2 axes per stick) + for (let i = 0; i < currentState.axes.length; i += 2) { + // Horizontal axes are even numbered + let x = parseFloat(currentState.axes[i].toFixed(4)); + + // Vertical axes are odd numbered + // https://w3c.github.io/gamepad/#remapping Gamepad browser side standard mapping has positive down, negative up. This is downright disgusting. So we fix it. + let y = -parseFloat(currentState.axes[i + 1].toFixed(4)); + + // UE's analog axes follow the same order as the browsers, but start at index 1 so we will offset as such + toStreamerHandlers.GamepadAnalog("GamepadAnalog", [j, i + 1, x]); // Horizontal axes, only offset by 1 + toStreamerHandlers.GamepadAnalog("GamepadAnalog", [j, i + 2, y]); // Vertical axes, offset by two (1 to match UEs axes convention and then another 1 for the vertical axes) } - } + controllers[j].prevState = currentState; } - // Iterate over gamepad axes (we will increment in lots of 2 as there is 2 axes per stick) - for (let i = 0; i < currentState.axes.length; i += 2) { - // Horizontal axes are even numbered - let x = parseFloat(currentState.axes[i].toFixed(4)); - - // Vertical axes are odd numbered - // https://w3c.github.io/gamepad/#remapping Gamepad browser side standard mapping has positive down, negative up. This is downright disgusting. So we fix it. - let y = -parseFloat(currentState.axes[i + 1].toFixed(4)); - - // UE's analog axes follow the same order as the browsers, but start at index 1 so we will offset as such - toStreamerHandlers.GamepadAnalog("GamepadAnalog", [j, i + 1, x]); // Horizontal axes, only offset by 1 - toStreamerHandlers.GamepadAnalog("GamepadAnalog", [j, i + 2, y]); // Vertical axes, offset by two (1 to match UEs axes convention and then another 1 for the vertical axes) - } - controllers[j].prevState = currentState; - } - rAF(updateStatus); + rAF(updateStatus); } function gamepadConnectHandler(e) { - console.log("Gamepad connect handler"); - gamepad = e.gamepad; - controllers[gamepad.index] = {}; - controllers[gamepad.index].currentState = gamepad; - controllers[gamepad.index].prevState = gamepad; - console.log("Gamepad: " + gamepad.id + " connected"); - rAF(updateStatus); + console.log("Gamepad connect handler"); + gamepad = e.gamepad; + controllers[gamepad.index] = {}; + controllers[gamepad.index].currentState = gamepad; + controllers[gamepad.index].prevState = gamepad; + console.log("Gamepad: " + gamepad.id + " connected"); + rAF(updateStatus); } function gamepadDisconnectHandler(e) { - console.log("Gamepad disconnect handler"); - console.log("Gamepad: " + e.gamepad.id + " disconnected"); - delete controllers[e.gamepad.index]; + console.log("Gamepad disconnect handler"); + console.log("Gamepad: " + e.gamepad.id + " disconnected"); + delete controllers[e.gamepad.index]; } + function fullscreen() { - // if already full screen; exit - // else go fullscreen - if ( - document.fullscreenElement || - document.webkitFullscreenElement || - document.mozFullScreenElement || - document.msFullscreenElement - ) { - if (document.exitFullscreen) { - document.exitFullscreen(); - } else if (document.mozCancelFullScreen) { - document.mozCancelFullScreen(); - } else if (document.webkitExitFullscreen) { - document.webkitExitFullscreen(); - } else if (document.msExitFullscreen) { - document.msExitFullscreen(); - } - } else { - let element; - //HTML elements controls - if (!(document.fullscreenEnabled || document.webkitFullscreenEnabled)) { - // Chrome and FireFox on iOS can only fullscreen a