1
/*
2
 * Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with
5
 * the License. A copy of the License is located at
6
 *
7
 *     http://aws.amazon.com/apache2.0/
8
 *
9
 * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
10
 * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
11
 * and limitations under the License.
12
 */
13 1
import * as React from 'react';
14 1
import { XR } from '@aws-amplify/xr';
15 1
import { ConsoleLogger as Logger } from '@aws-amplify/core';
16 1
import { IconButton } from './IconButton';
17 1
import { Loading } from './Loading';
18 1
import * as AmplifyUI from '@aws-amplify/ui';
19

20 1
import { sumerianScene } from '../Amplify-UI/data-test-attributes';
21

22 1
const SCENE_CONTAINER_DOM_ID = 'scene-container-dom-id';
23 1
const SCENE_DOM_ID = 'scene-dom-id';
24

25 1
const logger = new Logger('SumerianScene');
26

27
interface ISumerianSceneProps {
28
	sceneName: string;
29
}
30

31
interface ISumerianSceneState {
32
	showEnableAudio: boolean;
33
	muted: boolean;
34
	loading: boolean;
35
	percentage: number;
36
	isFullscreen: boolean;
37
	sceneError: any;
38
	isVRPresentationActive: boolean;
39
}
40

41 1
export class SumerianScene extends React.Component<
42
	ISumerianSceneProps,
43
	ISumerianSceneState
44
	> {
45
	constructor(props) {
46 1
		super(props);
47

48 1
		this.state = {
49
			showEnableAudio: false,
50
			muted: false,
51
			loading: true,
52
			percentage: 0,
53
			isFullscreen: false,
54
			sceneError: null,
55
			isVRPresentationActive: false,
56
		};
57
	}
58

59 1
	setStateAsync(state) {
60 1
		return new Promise(resolve => {
61 1
			this.setState(state, resolve);
62
		});
63
	}
64

65 1
	componentDidMount() {
66 1
		document.addEventListener(
67
			'fullscreenchange',
68
			this.onFullscreenChange.bind(this)
69
		);
70 1
		document.addEventListener(
71
			'webkitfullscreenchange',
72
			this.onFullscreenChange.bind(this)
73
		);
74 1
		document.addEventListener(
75
			'mozfullscreenchange',
76
			this.onFullscreenChange.bind(this)
77
		);
78 1
		document.addEventListener(
79
			'MSFullscreenChange',
80
			this.onFullscreenChange.bind(this)
81
		);
82

83 1
		this.loadAndSetupScene(this.props.sceneName, SCENE_DOM_ID);
84
	}
85

86 1
	componentWillUnmount() {
87 0
		document.removeEventListener(
88
			'fullscreenchange',
89
			this.onFullscreenChange.bind(this)
90
		);
91 0
		document.removeEventListener(
92
			'webkitfullscreenchange',
93
			this.onFullscreenChange.bind(this)
94
		);
95 0
		document.removeEventListener(
96
			'mozfullscreenchange',
97
			this.onFullscreenChange.bind(this)
98
		);
99 0
		document.removeEventListener(
100
			'MSFullscreenChange',
101
			this.onFullscreenChange.bind(this)
102
		);
103
	}
104

105 1
	async loadAndSetupScene(sceneName, sceneDomId) {
106 1
		this.setStateAsync({ loading: true });
107 1
		const sceneOptions = {
108
			progressCallback: progress => {
109 0
				const percentage = progress * 100;
110 0
				this.setState({ percentage });
111
			},
112
		};
113
		try {
114 1
			await XR.loadScene(sceneName, sceneDomId, sceneOptions);
115
		} catch (e) {
116 1
			const sceneError = {
117
				displayText: 'Failed to load scene',
118
				error: e,
119
			};
120 1
			logger.error(sceneError.displayText, sceneError.error);
121 1
			this.setStateAsync({ sceneError });
122 1
			return;
123
		}
124

125 0
		XR.start(sceneName);
126

127 0
		this.setStateAsync({
128
			muted: XR.isMuted(sceneName),
129
			isVRPresentationActive: XR.isVRPresentationActive(sceneName),
130
			loading: false,
131
		});
132

133 0
		XR.onSceneEvent(sceneName, 'AudioEnabled', () =>
134 0
			this.setStateAsync({ showEnableAudio: false })
135
		);
136 0
		XR.onSceneEvent(sceneName, 'AudioDisabled', () =>
137 0
			this.setStateAsync({ showEnableAudio: true })
138
		);
139
	}
140

141 1
	setMuted(muted) {
142 1
		if (this.state.showEnableAudio) {
143 0
			XR.enableAudio(this.props.sceneName);
144 0
			this.setState({ showEnableAudio: false });
145
		}
146

147 0
		XR.setMuted(this.props.sceneName, muted);
148 0
		this.setState({ muted });
149
	}
150

151 1
	onFullscreenChange() {
152 0
		const doc = document;
153 0
		this.setState({ isFullscreen: doc.fullscreenElement !== null });
154
	}
155

156 1
	async maximize() {
157 0
		const sceneDomElement = document.getElementById(SCENE_CONTAINER_DOM_ID);
158 0
		await sceneDomElement.requestFullscreen();
159
	}
160

161 1
	async minimize() {
162 0
		const doc = document;
163 1
		if (doc.exitFullscreen) {
164 0
			doc.exitFullscreen();
165 1
		} else if (doc.mozCancelFullScreen) {
166 0
			doc.mozCancelFullScreen();
167 1
		} else if (doc.webkitExitFullscreen) {
168 0
			doc.webkitExitFullscreen();
169
		}
170
	}
171

172 1
	toggleVRPresentation() {
173 0
		try {
174 1
			if (this.state.isVRPresentationActive) {
175 0
				XR.exitVR(this.props.sceneName);
176
			} else {
177 0
				XR.enterVR(this.props.sceneName);
178
			}
179
		} catch (e) {
180 0
			logger.error('Unable to start/stop WebVR System: ' + e.message);
181 0
			return;
182
		}
183 0
		this.setState({
184
			isVRPresentationActive: !this.state.isVRPresentationActive,
185
		});
186
	}
187

188 1
	render() {
189
		let muteButton;
190
		let enterOrExitVRButton;
191
		let screenSizeButton;
192

193 1
		if (XR.isSceneLoaded(this.props.sceneName)) {
194 1
			if (this.state.showEnableAudio) {
195 0
				muteButton = (
196
					<IconButton
197
						variant="sound-mute"
198
						tooltip="The scene is muted. Click to unmute."
199 0
						onClick={() => this.setMuted(false)}
200
						autoShowTooltip
201
					/>
202
				);
203 1
			} else if (XR.isMuted(this.props.sceneName)) {
204 0
				muteButton = (
205
					<IconButton
206
						variant="sound-mute"
207
						tooltip="Unmute"
208 0
						onClick={() => this.setMuted(false)}
209
					/>
210
				);
211
			} else {
212 0
				muteButton = (
213
					<IconButton
214
						variant="sound"
215
						tooltip="Mute"
216 0
						onClick={() => this.setMuted(true)}
217
					/>
218
				);
219
			}
220

221 1
			if (XR.isVRCapable(this.props.sceneName)) {
222 1
				if (this.state.isVRPresentationActive) {
223 0
					logger.info('VR Presentation Active');
224 0
					enterOrExitVRButton = (
225
						<IconButton
226
							variant="exit-vr"
227
							tooltip="Exit VR"
228 0
							onClick={() => this.toggleVRPresentation()}
229
						/>
230
					);
231
				} else {
232 0
					logger.info('VR Presentation Inactive');
233 0
					enterOrExitVRButton = (
234
						<IconButton
235
							variant="enter-vr"
236
							tooltip="Enter VR"
237 0
							onClick={() => this.toggleVRPresentation()}
238
						/>
239
					);
240
				}
241
			}
242

243 1
			if (this.state.isFullscreen) {
244 0
				screenSizeButton = (
245
					<IconButton
246
						variant="minimize"
247
						tooltip="Exit Fullscreen"
248 0
						onClick={() => this.minimize()}
249
					/>
250
				);
251
			} else {
252 0
				screenSizeButton = (
253
					<IconButton
254
						variant="maximize"
255
						tooltip="Fullscreen"
256 0
						onClick={() => this.maximize()}
257
					/>
258
				);
259
			}
260
		}
261

262 1
		return (
263
			<div
264
				id={SCENE_CONTAINER_DOM_ID}
265
				className={AmplifyUI.sumerianSceneContainer}
266
				data-test={sumerianScene.container}
267
			>
268
				<div
269
					id={SCENE_DOM_ID}
270
					className={AmplifyUI.sumerianScene}
271
					data-test={sumerianScene.sumerianScene}
272
				>
273 1
					{this.state.loading && (
274
						<Loading
275
							sceneName={this.props.sceneName}
276
							percentage={this.state.percentage}
277
							sceneError={this.state.sceneError}
278
						/>
279
					)}
280
				</div>
281
				<div className={AmplifyUI.sceneBar} data-test={sumerianScene.bar}>
282
					<span
283
						className={AmplifyUI.sceneActions}
284
						data-test={sumerianScene.actions}
285
					>
286
						{muteButton}
287
						{enterOrExitVRButton}
288
						{screenSizeButton}
289
					</span>
290
				</div>
291
			</div>
292
		);
293
	}
294 1
}
295

296
/**
297
 * @deprecated use named import
298
 */
299 1
export default SumerianScene;

Read our documentation on viewing source code .

Loading