diff --git a/front/dist/index.tmpl.html b/front/dist/index.tmpl.html
index 6264bbbb..112588e0 100644
--- a/front/dist/index.tmpl.html
+++ b/front/dist/index.tmpl.html
@@ -126,6 +126,15 @@
+
diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts
index 9192e533..cd83a0a5 100644
--- a/front/src/Phaser/Game/GameScene.ts
+++ b/front/src/Phaser/Game/GameScene.ts
@@ -97,6 +97,7 @@ import {waScaleManager} from "../Services/WaScaleManager";
import {peerStore} from "../../Stores/PeerStore";
import {EmoteManager} from "./EmoteManager";
import { InteractiveLayer } from "../Map/InteractiveLayer";
+import {videoManager} from "../../WebRtc/VideoManager";
export interface GameSceneInitInterface {
initPosition: PointInterface|null,
@@ -721,6 +722,19 @@ export class GameScene extends DirtyScene implements CenterListener {
}
}
+ private playVideo(url: string|number|boolean|undefined, loop=false): void {
+ if (url === undefined) {
+ videoManager.unloadVideo();
+ } else {
+ const realVideoPath = '' + url;
+ videoManager.loadVideo(realVideoPath);
+
+ if (loop) {
+ videoManager.loop();
+ }
+ }
+ }
+
private triggerOnMapLayerPropertyChange(){
this.gameMap.onPropertyChange('exitSceneUrl', (newValue, oldValue) => {
if (newValue) this.onMapExit(newValue as string);
@@ -866,6 +880,13 @@ ${escapedMessage}
this.popUpElements.set(openPopupEvent.popupId, domElement);
}));
+ this.gameMap.onPropertyChange('playVideo', (newValue, oldValue) => {
+ this.playVideo(newValue);
+ });
+
+ this.gameMap.onPropertyChange('playVideoLoop', (newValue, oldValue) => {
+ this.playVideo(newValue, true);
+ });
this.iframeSubscriptionList.push(iframeListener.closePopupStream.subscribe((closePopupEvent) => {
const popUpElement = this.popUpElements.get(closePopupEvent.popupId);
diff --git a/front/src/WebRtc/VideoManager.ts b/front/src/WebRtc/VideoManager.ts
new file mode 100644
index 00000000..b0f7425f
--- /dev/null
+++ b/front/src/WebRtc/VideoManager.ts
@@ -0,0 +1,159 @@
+import {HtmlUtils} from "./HtmlUtils";
+import {isUndefined} from "generic-type-guard";
+
+enum videoStates {
+ closed = 0,
+ loading = 1,
+ playing = 2
+}
+
+const videoPlayerDivId = "videoplayer";
+const videoPlayerCtrlId = "videoplayerctrl";
+const animationTime = 500;
+
+class VideoManager {
+ private opened = videoStates.closed;
+
+ private videoPlayerDiv: HTMLDivElement;
+ private videoPlayerCtrl: HTMLDivElement;
+ private videoPlayerElem: HTMLVideoElement | undefined;
+
+ private volume = 1;
+ private muted = false;
+ private decreaseWhileTalking = true;
+ private volumeReduced = false;
+
+ constructor() {
+ this.videoPlayerDiv = HtmlUtils.getElementByIdOrFail(videoPlayerDivId);
+ this.videoPlayerCtrl = HtmlUtils.getElementByIdOrFail(videoPlayerCtrlId);
+
+ const storedVolume = localStorage.getItem('volume')
+ if (storedVolume === null) {
+ this.setVolume(1);
+ } else {
+ this.volume = parseFloat(storedVolume);
+ //HtmlUtils.getElementByIdOrFail('videoplayer_volume').value = storedVolume;
+ }
+
+ //HtmlUtils.getElementByIdOrFail('videoplayer_volume').value = '' + this.volume;
+ }
+
+ private close(): void {
+ this.videoPlayerCtrl.classList.remove('loading');
+ this.videoPlayerCtrl.classList.add('hidden');
+ this.opened = videoStates.closed;
+ }
+
+ private load(): void {
+ this.videoPlayerCtrl.classList.remove('hidden');
+ this.videoPlayerCtrl.classList.add('loading');
+ this.opened = videoStates.loading;
+ }
+
+ private open(): void {
+ this.videoPlayerCtrl.classList.remove('hidden', 'loading');
+ this.opened = videoStates.playing;
+ }
+
+ private changeVolume(talking = false): void {
+ if (!isUndefined(this.videoPlayerElem)) {
+ this.videoPlayerElem.volume = this.naturalVolume(talking && this.decreaseWhileTalking);
+ this.videoPlayerElem.muted = this.muted;
+ }
+ }
+
+ private naturalVolume(makeSofter: boolean = false): number {
+ const volume = this.volume
+ const retVol = makeSofter && !this.volumeReduced ? Math.pow(volume * 0.5, 3) : volume
+ this.volumeReduced = makeSofter
+ return retVol;
+ }
+
+ private setVolume(volume: number): void {
+ this.volume = volume;
+ localStorage.setItem('volume', '' + volume);
+ }
+
+
+ public loadVideo(url: string): void {
+ this.load();
+
+ /* Solution 1, remove whole video player */
+ this.videoPlayerDiv.innerHTML = ''; // necessary, if switching from one video context to another! (else both streams would play simultaneously)
+
+ this.videoPlayerElem = document.createElement('video');
+ this.videoPlayerElem.id = 'videoplayerelem';
+ this.videoPlayerElem.controls = true;
+ this.videoPlayerElem.preload = 'none';
+
+ const srcElem = document.createElement('source');
+ srcElem.src = url;
+
+ this.videoPlayerElem.append(srcElem);
+
+ this.videoPlayerDiv.append(this.videoPlayerElem);
+ this.changeVolume();
+ this.videoPlayerElem.play();
+
+ /*const muteElem = HtmlUtils.getElementByIdOrFail('videoplayer_mute');
+ muteElem.onclick = (ev: Event)=> {
+ this.muted = !this.muted;
+ this.changeVolume();
+
+ if (this.muted) {
+ HtmlUtils.getElementByIdOrFail('videoplayer_volume_icon_playing').classList.add('muted');
+ } else {
+ HtmlUtils.getElementByIdOrFail('videoplayer_volume_icon_playing').classList.remove('muted');
+ }
+ }
+
+ const volumeElem = HtmlUtils.getElementByIdOrFail('videoplayer_volume');
+ volumeElem.oninput = (ev: Event)=> {
+ this.setVolume(parseFloat((ev.currentTarget).value));
+ this.changeVolume();
+
+ (ev.currentTarget).blur();
+ }*/
+
+ const decreaseElem = HtmlUtils.getElementByIdOrFail('videoplayer_decrease_while_talking');
+ decreaseElem.oninput = (ev: Event)=> {
+ this.decreaseWhileTalking = (ev.currentTarget).checked;
+ this.changeVolume();
+ }
+
+ this.open();
+ }
+
+ public loop(): void {
+ if (this.videoPlayerElem !== undefined) {
+ this.videoPlayerElem.loop = true;
+ }
+ }
+
+ public unloadVideo(): void {
+ try {
+ const videoElem = HtmlUtils.getElementByIdOrFail('videoplayerelem');
+ this.volume = videoElem.volume;
+ this.muted = videoElem.muted;
+ videoElem.pause();
+ videoElem.loop = false;
+ videoElem.src = "";
+ videoElem.innerHTML = "";
+ videoElem.load();
+ } catch (e) {
+ console.log('No video element loaded to unload');
+ }
+
+ this.close();
+ }
+
+ public decreaseVolume(): void {
+ this.changeVolume(true);
+ }
+
+ public restoreVolume(): void {
+ this.changeVolume(false);
+ }
+}
+
+export const videoManager = new VideoManager();
diff --git a/front/style/style.css b/front/style/style.css
index bb6fe54a..3a5872ea 100644
--- a/front/style/style.css
+++ b/front/style/style.css
@@ -581,6 +581,30 @@ input[type=range]:focus::-ms-fill-upper {
background: #FFFFFF;
}
+#videoplayerctrl {
+ position: fixed;
+ width: 25%;
+ top: 0;
+ right: 75%;
+ transform: translate(50%, 0);
+ padding: 0.3rem 0.5rem;
+ color: white;
+ transition: transform 0.5s;
+}
+
+/*
+ * sollte eigentlich in den aspect-ratio teil ..
+ */
+#videoplayerctrl.loading {
+ transform: translate(50%, -90%);
+}
+#videoplayerctrl.hidden {
+ transform: translate(50%, -100%);
+}
+
+#videoplayerelem {
+ width: 100%;
+}
.game-overlay {
display: none;