/
sumerian-scene.component.core.ts
253 lines (232 loc) · 13.4 KB
/
sumerian-scene.component.core.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
/*
* Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with
* the License. A copy of the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
import { Component, OnInit, OnDestroy, Input } from '@angular/core';
import { AmplifyService } from '../../../providers';
import * as AmplifyUI from '@aws-amplify/ui';
import { sumerianScene } from '../../../assets/data-test-attributes';
const template = `
<div id="sumerian-scene-container" class={{amplifyUI.sumerianSceneContainer}} data-test="${sumerianScene.container}">
<div id="sumerian-scene-dom-id" class={{amplifyUI.sumerianScene}} data-test="${sumerianScene.sumerianScene}">
<sumerian-scene-loading-core *ngIf="loading" loadPercentage={{loadPercentage}} sceneName={{sceneName}} sceneError={{sceneError}} data-test="${sumerianScene.loading}"></sumerian-scene-loading-core>
</div>
<div *ngIf="!loading" class={{amplifyUI.sceneBar}} data-test="${sumerianScene.bar}">
<span class={{amplifyUI.sceneActions}} data-test="${sumerianScene.actions}">
<div [ngClass]="[amplifyUI.tooltip, showEnableAudio ? amplifyUI.autoShowTooltip : '']" [attr.data-text]="showEnableAudio ? 'The scene is muted. Click to unmute.' : (muted ? 'Unmute' : 'Mute')" (click)="muted ? setMuted(false) : setMuted(true)">
<button class={{amplifyUI.actionButton}}>
<svg *ngIf="muted" width="19px" height="19px" viewBox="0 0 19 19" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="icons/minis/volumeOff" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M3.48026899,12.9630494 C3.63825091,12.9630494 3.79237961,13.0108921 3.92264322,13.1003479 L8.77467683,16.8113609 C9.29423971,17.1679383 10,16.7950396 10,16.1637406 L10,3.78619489 C10,3.15489596 9.29423971,2.78199725 8.77467683,3.13857463 L3.92264322,6.84545211 C3.79237961,6.93490793 3.63825091,6.9827506 3.48026899,6.9827506 L1.78294894,6.9827506 C1.3505185,6.9827506 1,7.33409518 1,7.76754476 L1,12.1781306 C1,12.6117048 1.3505185,12.9630494 1.78294894,12.9630494 L3.48026899,12.9630494 Z M17.2118156,7 L15.0918385,9.11997713 L12.9718614,7 L12,7.97174685 L14.1200917,10.091724 L12,12.2118156 L12.9718614,13.1835625 L15.0918385,11.0635854 L17.2118156,13.1835625 L18.1835625,12.2118156 L16.0635854,10.091724 L18.1835625,7.97174685 L17.2118156,7 Z" id="Fill-2" fill="#FFFFFF"></path>
</g>
</svg>
<svg *ngIf="!muted" width="19px" height="19px" viewBox="0 0 19 19" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="icons/minis/volumeOn" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M3.48026899,12.9630494 L1.78294894,12.9630494 C1.3505185,12.9630494 1,12.6117048 1,12.1781306 L1,7.76754476 C1,7.33409518 1.3505185,6.9827506 1.78294894,6.9827506 L3.48026899,6.9827506 C3.63825091,6.9827506 3.79237961,6.93490793 3.92264322,6.84545211 L8.77467683,3.13857463 C9.29423971,2.78199725 10,3.15489596 10,3.78619489 L10,16.1637406 C10,16.7950396 9.29423971,17.1679383 8.77467683,16.8113609 L3.92264322,13.1003479 C3.79237961,13.0108921 3.63825091,12.9630494 3.48026899,12.9630494 Z M14.9270376,3.03232286 C15.1729267,3.03232286 15.4040399,3.12815658 15.5777627,3.3022351 C17.3699891,5.09889099 18.3570052,7.48235058 18.3570052,10.0135053 C18.3570052,12.54466 17.3699891,14.9281196 15.5777627,16.7247755 C15.4041045,16.898854 15.1729914,16.9947524 14.9270052,16.9947524 C14.6820861,16.9947524 14.4515549,16.899436 14.2777674,16.7263598 C13.9192316,16.3684383 13.9185203,15.7852882 14.2762477,15.4264291 C15.7222893,13.9769926 16.5186727,12.0545954 16.5186727,10.0135053 C16.5186727,7.97241524 15.7222893,6.05001801 14.2762154,4.60058152 C13.9184879,4.24175473 13.9191992,3.65857229 14.277832,3.30065081 C14.4514256,3.1275746 14.6819567,3.03232286 14.9270376,3.03232286 Z M13.5730665,6.11570485 C14.6133991,7.15574642 15.1862998,8.54003279 15.1862998,10.0134924 C15.1862998,11.4892799 14.6113945,12.8741159 13.5675376,13.9128965 C13.3942351,14.0855848 13.1639626,14.1806425 12.9191727,14.1806425 C12.6727016,14.1806425 12.4412975,14.0844531 12.2677039,13.9097926 C12.0944984,13.7358111 11.9994406,13.5047303 11.9999903,13.2592291 C12.0005723,13.0136956 12.096794,12.7831644 12.2708079,12.6100882 C12.9654406,11.9185917 13.3479995,10.996467 13.3479995,10.0134924 C13.3479995,9.03119677 12.966346,8.1086194 12.2733298,7.4157649 C11.9150203,7.05745543 11.9149233,6.47436998 12.2731358,6.11589885 C12.4467617,5.94224065 12.6775838,5.84666559 12.923085,5.84666559 C13.1685538,5.84666559 13.3993436,5.94220831 13.5730665,6.11570485 Z" id="Fill-2" fill="#FFFFFF"></path>
</g>
</svg>
</button>
</div>
<div *ngIf="isVRCapable && !isVRPresentationActive" class={{amplifyUI.tooltip}} data-text="Enter VR" (click)="toggleVRPresentation()">
<button class={{amplifyUI.actionButton}}>
<svg width="19px" height="19px" viewBox="0 0 17 10" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="VRon" fill="#FFFFFF" fill-rule="nonzero">
<path d="M15.7856977,0.02395184 L15.8915734,0.02395184 C16.5037405,0.02395184 17,0.520211324 17,1.13237842 L17,1.54663675 L17,8.8915038 C17,9.5034193 16.4560011,10 15.7856977,10 L12.0095825,10 C9.98324439,7.1593807 8.80676009,5.741338 8.48012959,5.74587199 C8.16206045,5.75028714 7.01003321,7.1683298 5.02404785,10 L1.21426911,10 C0.543965735,10 3.32031236e-05,9.5034193 3.32031236e-05,8.8915038 L3.32031236e-05,1.54663675 L3.32031236e-05,1.13237842 L3.32031236e-05,1.13237842 C3.32031236e-05,0.520211324 0.496292687,0.02395184 1.10845978,0.02395184 L1.21426911,0.02395184 L15.7856977,0.02395184 Z M4.5,6 C5.32842712,6 6,5.32842712 6,4.5 C6,3.67157288 5.32842712,3 4.5,3 C3.67157288,3 3,3.67157288 3,4.5 C3,5.32842712 3.67157288,6 4.5,6 Z M12.5,6 C13.3284271,6 14,5.32842712 14,4.5 C14,3.67157288 13.3284271,3 12.5,3 C11.6715729,3 11,3.67157288 11,4.5 C11,5.32842712 11.6715729,6 12.5,6 Z" id="Fill-1"></path>
</g>
</g>
</svg>
</button>
</div>
<div *ngIf="isVRCapable && isVRPresentationActive" class={{amplifyUI.tooltip}} data-text="Exit VR" (click)="toggleVRPresentation()">
<button class={{amplifyUI.actionButton}}>
<svg width="19px" height="19px" viewBox="0 0 19 19" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="icons/minis/VRon-Copy" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Group-7-Copy" transform="translate(1.000000, 3.000000)" fill="#FFFFFF">
<path d="M15.7856977,3.02395184 L17,3.02395184 L17,4.13237842 L17,4.54663675 L17,11.8915038 C17,12.5034193 16.4560011,13 15.7856977,13 L12.0095825,13 C9.98324439,10.1593807 8.80676009,8.741338 8.48012959,8.74587199 C8.16206045,8.75028714 7.01003321,10.1683298 5.02404785,13 L1.21426911,13 C0.543965735,13 3.32031236e-05,12.5034193 3.32031236e-05,11.8915038 L3.32031236e-05,4.54663675 L3.32031236e-05,4.13237842 L3.32031236e-05,3.02395184 L1.21426911,3.02395184 L15.7856977,3.02395184 Z M4.5,9 C5.32842712,9 6,8.32842712 6,7.5 C6,6.67157288 5.32842712,6 4.5,6 C3.67157288,6 3,6.67157288 3,7.5 C3,8.32842712 3.67157288,9 4.5,9 Z M12.5,9 C13.3284271,9 14,8.32842712 14,7.5 C14,6.67157288 13.3284271,6 12.5,6 C11.6715729,6 11,6.67157288 11,7.5 C11,8.32842712 11.6715729,9 12.5,9 Z M2.5486669,0 L14.420089,0 C14.7977406,0 15.1613805,0.149260956 15.4374308,0.417695511 L16.9999668,2.00634766 L0,2.00634766 L1.58537972,0.395493117 C1.84682061,0.141306827 2.19106994,0 2.5486669,0 Z" id="Fill-1"></path>
</g>
</g>
</svg>
</button>
</div>
<div *ngIf="!isFullscreen" class={{amplifyUI.tooltip}} data-text="Fullscreen">
<button class={{amplifyUI.actionButton}} (click)="maximize()">
<svg width="19px" height="19px" viewBox="0 0 19 19" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="icons/minis/screenfull" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M2.04162598,3 L2.04162598,16 L17.0147705,16 L17.0147705,3 L2.04162598,3 Z M1,2 L18,2 L18,17 L1,17 L1,2 Z M3,4 L16,4 L16,15 L3,15 L3,4 Z" id="Rectangle-Copy" fill="#FFFFFF" fill-rule="nonzero"></path>
</g>
</svg>
</button>
</div>
<div *ngIf="isFullscreen" class={{amplifyUI.tooltip}} data-text="Exit Fullscreen">
<button class={{amplifyUI.actionButton}} (click)="minimize()">
<svg width="19px" height="19px" viewBox="0 0 19 19" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="icons/minis/screensmall" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M11,16 L17.0147705,16 L17.0147705,3 L2.04162598,3 L2.04162598,10 L11,10 L11,16 Z M1,2 L18,2 L18,17 L1,17 L1,2 Z" id="Rectangle" fill="#FFFFFF" fill-rule="nonzero"></path>
</g>
</svg>
</button>
</div>
</span>
</div>
</div>
`;
@Component({
selector: 'sumerian-scene-core',
template,
})
export class SumerianSceneComponentCore implements OnInit, OnDestroy {
@Input() sceneName: string;
loading = false;
loadPercentage = 0;
muted = false;
showEnableAudio = false;
isVRCapable = false;
isVRPresentationActive = false;
isFullscreen = false;
sceneError = null;
amplifyUI: any;
protected logger: any;
@Input()
set data(data: any) {
this.sceneName = data.sceneName;
}
constructor(protected amplifyService: AmplifyService) {
this.amplifyUI = AmplifyUI;
this.logger = this.amplifyService.logger('SumerianSceneComponentCore');
}
ngOnInit() {
document.addEventListener(
'fullscreenchange',
this.onFullscreenChange.bind(this)
);
document.addEventListener(
'webkitfullscreenchange',
this.onFullscreenChange.bind(this)
);
document.addEventListener(
'mozfullscreenchange',
this.onFullscreenChange.bind(this)
);
document.addEventListener(
'MSFullscreenChange',
this.onFullscreenChange.bind(this)
);
if (!this.amplifyService.xr()) {
throw new Error('XR module not registered on AmplifyService provider');
}
this.loadAndStartScene();
}
ngOnDestroy() {
document.removeEventListener(
'fullscreenchange',
this.onFullscreenChange.bind(this)
);
document.removeEventListener(
'webkitfullscreenchange',
this.onFullscreenChange.bind(this)
);
document.removeEventListener(
'mozfullscreenchange',
this.onFullscreenChange.bind(this)
);
document.removeEventListener(
'MSFullscreenChange',
this.onFullscreenChange.bind(this)
);
}
progressCallback = progress => {
const percentage = progress * 100;
this.loadPercentage = percentage;
};
async loadAndStartScene() {
this.loading = true;
const sceneOptions = {
progressCallback: this.progressCallback,
};
try {
await this.amplifyService
.xr()
.loadScene(this.sceneName, 'sumerian-scene-dom-id', sceneOptions);
} catch (e) {
this.sceneError = 'Failed to load scene';
this.logger.error(this.sceneError, e);
return;
}
this.amplifyService.xr().start(this.sceneName);
this.loading = false;
this.muted = this.amplifyService.xr().isMuted(this.sceneName);
this.isVRCapable = this.amplifyService.xr().isVRCapable(this.sceneName);
this.isVRPresentationActive = this.amplifyService
.xr()
.isVRPresentationActive(this.sceneName);
this.amplifyService
.xr()
.onSceneEvent(
this.sceneName,
'AudioEnabled',
() => (this.showEnableAudio = false)
);
this.amplifyService
.xr()
.onSceneEvent(
this.sceneName,
'AudioDisabled',
() => (this.showEnableAudio = true)
);
}
setMuted(muted) {
this.muted = muted;
this.amplifyService.xr().setMuted(this.sceneName, muted);
if (this.showEnableAudio) {
this.amplifyService.xr().enableAudio(this.sceneName);
this.showEnableAudio = false;
}
}
toggleVRPresentation() {
try {
if (this.isVRPresentationActive) {
this.amplifyService.xr().exitVR(this.sceneName);
} else {
this.amplifyService.xr().enterVR(this.sceneName);
}
} catch (e) {
this.logger.error('Unable to start/stop WebVR System: ' + e.message);
return;
}
this.isVRPresentationActive = !this.isVRPresentationActive;
}
onFullscreenChange() {
const doc: any = document;
this.isFullscreen = doc.fullscreenElement !== null;
}
async maximize() {
const sceneDomElement: any = document.getElementById(
'sumerian-scene-container'
);
const requestFullScreen =
sceneDomElement.requestFullscreen ||
sceneDomElement.msRequestFullscreen ||
sceneDomElement.mozRequestFullScreen ||
sceneDomElement.webkitRequestFullscreen;
requestFullScreen.call(sceneDomElement);
}
async minimize() {
const doc: any = document;
if (doc.exitFullscreen) {
doc.exitFullscreen();
} else if (doc.mozCancelFullScreen) {
doc.mozCancelFullScreen();
} else if (doc.webkitExitFullscreen) {
doc.webkitExitFullscreen();
}
}
}