elation-engine 0.9.113 → 0.9.115

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/css/systems/render.css +5 -1
  2. package/package.json +1 -1
  3. package/scripts/assets.js +103 -20
  4. package/scripts/assetworker.js +18 -1
  5. package/scripts/external/holoplay.js +1494 -0
  6. package/scripts/external/octree.js +0 -0
  7. package/scripts/external/three/CSS3DRenderer.js +46 -43
  8. package/scripts/external/three/CubemapToEquirectangular.js +1 -1
  9. package/scripts/external/three/three-extras.js +1553 -392
  10. package/scripts/external/three/three-icosa.js +2575 -0
  11. package/scripts/external/three/three-loaders.js +925 -133
  12. package/scripts/external/three/three-postprocessing.js +3 -3
  13. package/scripts/external/three/three-r116dev.js +50930 -0
  14. package/scripts/external/three/three-spotlighttextures.js +50953 -0
  15. package/scripts/external/three/three-vrm.js +2 -2
  16. package/scripts/external/three/three-working.js +35968 -0
  17. package/scripts/external/three/three.js +38532 -24087
  18. package/scripts/external/three-mesh-bvh.js +5370 -0
  19. package/scripts/external/three-old/BVHLoader.js +406 -0
  20. package/scripts/external/three-old/ColladaLoader.js +5519 -0
  21. package/scripts/external/three-old/ColladaLoader2.js +1694 -0
  22. package/scripts/external/three-old/CubemapToEquirectangular.js +188 -0
  23. package/scripts/external/three-old/DDSLoader.js +269 -0
  24. package/scripts/external/three-old/FBXLoader-mine.js +5063 -0
  25. package/scripts/external/three-old/FBXLoader.js +5112 -0
  26. package/scripts/external/three-old/FlyControls.js +295 -0
  27. package/scripts/external/three-old/GLTF2Loader.js +2950 -0
  28. package/scripts/external/three-old/GLTFLoader.js +2213 -0
  29. package/scripts/external/three-old/JSONLoader.js +435 -0
  30. package/scripts/external/three-old/MTLLoader.js +533 -0
  31. package/scripts/external/three-old/OBJLoader-experimental.js +874 -0
  32. package/scripts/external/three-old/OBJLoader-working.js +727 -0
  33. package/scripts/external/three-old/OBJLoader.js +723 -0
  34. package/scripts/external/three-old/OBJMTLLoader.js +440 -0
  35. package/scripts/external/three-old/OrbitControls.js +592 -0
  36. package/scripts/external/three-old/PLYLoader.js +517 -0
  37. package/scripts/external/three-old/TransformControls.js +1100 -0
  38. package/scripts/external/three-old/VRMLLoader.js +1021 -0
  39. package/scripts/external/three-old/glTFLoader-combined.js +2513 -0
  40. package/scripts/external/three-old/nodethree.js +44018 -0
  41. package/scripts/external/three-old/render/BleachBypassShader.js +64 -0
  42. package/scripts/external/three-old/render/BloomPass.js +116 -0
  43. package/scripts/external/three-old/render/CSS3DRenderer.js +310 -0
  44. package/scripts/external/three-old/render/ClearPass.js +44 -0
  45. package/scripts/external/three-old/render/ConvolutionShader.js +101 -0
  46. package/scripts/external/three-old/render/CopyShader.js +46 -0
  47. package/scripts/external/three-old/render/EffectComposer.js +211 -0
  48. package/scripts/external/three-old/render/FXAAShader.js +88 -0
  49. package/scripts/external/three-old/render/FilmPass.js +60 -0
  50. package/scripts/external/three-old/render/FilmShader.js +104 -0
  51. package/scripts/external/three-old/render/ManualMSAARenderPass.js +168 -0
  52. package/scripts/external/three-old/render/MaskPass.js +97 -0
  53. package/scripts/external/three-old/render/OculusRenderPass.js +84 -0
  54. package/scripts/external/three-old/render/OculusRiftEffect.js +240 -0
  55. package/scripts/external/three-old/render/PortalRenderPass.js +166 -0
  56. package/scripts/external/three-old/render/RecordingPass.js +208 -0
  57. package/scripts/external/three-old/render/RenderPass.js +57 -0
  58. package/scripts/external/three-old/render/SSAOShader.js +259 -0
  59. package/scripts/external/three-old/render/SepiaShader.js +54 -0
  60. package/scripts/external/three-old/render/ShaderPass.js +66 -0
  61. package/scripts/external/three-old/render/VREffect.js +482 -0
  62. package/scripts/external/three-old/shimthree.js +23 -0
  63. package/scripts/external/three-old/stats.js +6 -0
  64. package/scripts/external/three-old/three-88dev.js +45004 -0
  65. package/scripts/external/three-old/three-backgroundoptimization.js +44432 -0
  66. package/scripts/external/three-old/three-updates.js +44735 -0
  67. package/scripts/external/three-old/three-working.js +44719 -0
  68. package/scripts/external/three-old/three.js +44431 -0
  69. package/scripts/external/three-old/threex.rendererstats.js +66 -0
  70. package/scripts/external/three-old/tween.js +13 -0
  71. package/scripts/external/webvr-polyfill-new.js +3497 -0
  72. package/scripts/external/webvr-polyfill-newest.js +3491 -0
  73. package/scripts/external/webvr-polyfill-old.js +6337 -0
  74. package/scripts/geometries.js +2 -2
  75. package/scripts/math.js +6 -6
  76. package/scripts/systems/admin.js +1 -1
  77. package/scripts/systems/controls.js +6 -4
  78. package/scripts/systems/physics.js +10 -10
  79. package/scripts/systems/render.js +58 -20
  80. package/scripts/systems/render2.js +38 -0
  81. package/scripts/things/camera.js +6 -1
  82. package/scripts/things/generic-trackedvectors.js +1875 -0
  83. package/scripts/things/generic.js +3 -4
  84. package/scripts/things/label2d.js +1 -1
  85. package/scripts/things/leapmotion.js +6 -6
  86. package/scripts/things/menu.js +1 -1
  87. package/scripts/things/player-bak.js +638 -0
  88. package/scripts/things/player.js +28 -10
  89. package/scripts/things/skysphere.js +1 -1
  90. package/scripts/things/terrain.js +1 -1
  91. package/scripts/things/text.js +1 -1
@@ -0,0 +1,3491 @@
1
+ /**
2
+ * @license
3
+ * webvr-polyfill
4
+ * Copyright (c) 2015-2017 Google
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ /**
19
+ * @license
20
+ * cardboard-vr-display
21
+ * Copyright (c) 2015-2017 Google
22
+ * Licensed under the Apache License, Version 2.0 (the "License");
23
+ * you may not use this file except in compliance with the License.
24
+ * You may obtain a copy of the License at
25
+ *
26
+ * http://www.apache.org/licenses/LICENSE-2.0
27
+ *
28
+ * Unless required by applicable law or agreed to in writing, software
29
+ * distributed under the License is distributed on an "AS IS" BASIS,
30
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
31
+ * See the License for the specific language governing permissions and
32
+ * limitations under the License.
33
+ */
34
+
35
+ /**
36
+ * @license
37
+ * webvr-polyfill-dpdb
38
+ * Copyright (c) 2017 Google
39
+ * Licensed under the Apache License, Version 2.0 (the "License");
40
+ * you may not use this file except in compliance with the License.
41
+ * You may obtain a copy of the License at
42
+ *
43
+ * http://www.apache.org/licenses/LICENSE-2.0
44
+ *
45
+ * Unless required by applicable law or agreed to in writing, software
46
+ * distributed under the License is distributed on an "AS IS" BASIS,
47
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
48
+ * See the License for the specific language governing permissions and
49
+ * limitations under the License.
50
+ */
51
+
52
+ /**
53
+ * @license
54
+ * wglu-preserve-state
55
+ * Copyright (c) 2016, Brandon Jones.
56
+ *
57
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
58
+ * of this software and associated documentation files (the "Software"), to deal
59
+ * in the Software without restriction, including without limitation the rights
60
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
61
+ * copies of the Software, and to permit persons to whom the Software is
62
+ * furnished to do so, subject to the following conditions:
63
+ *
64
+ * The above copyright notice and this permission notice shall be included in
65
+ * all copies or substantial portions of the Software.
66
+ *
67
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
68
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
69
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
70
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
71
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
72
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
73
+ * THE SOFTWARE.
74
+ */
75
+
76
+ /**
77
+ * @license
78
+ * nosleep.js
79
+ * Copyright (c) 2017, Rich Tibbett
80
+ *
81
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
82
+ * of this software and associated documentation files (the "Software"), to deal
83
+ * in the Software without restriction, including without limitation the rights
84
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
85
+ * copies of the Software, and to permit persons to whom the Software is
86
+ * furnished to do so, subject to the following conditions:
87
+ *
88
+ * The above copyright notice and this permission notice shall be included in
89
+ * all copies or substantial portions of the Software.
90
+ *
91
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
92
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
93
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
94
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
95
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
96
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
97
+ * THE SOFTWARE.
98
+ */
99
+
100
+ (function (global, factory) {
101
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
102
+ typeof define === 'function' && define.amd ? define(factory) :
103
+ (global.WebVRPolyfill = factory());
104
+ }(this, (function () { 'use strict';
105
+
106
+ var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
107
+
108
+
109
+
110
+ function unwrapExports (x) {
111
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
112
+ }
113
+
114
+ function createCommonjsModule(fn, module) {
115
+ return module = { exports: {} }, fn(module, module.exports), module.exports;
116
+ }
117
+
118
+ var race = function race(promises) {
119
+ if (Promise.race) {
120
+ return Promise.race(promises);
121
+ }
122
+ return new Promise(function (resolve, reject) {
123
+ for (var i = 0; i < promises.length; i++) {
124
+ promises[i].then(resolve, reject);
125
+ }
126
+ });
127
+ };
128
+
129
+ var isMobile = function isMobile() {
130
+ return (/Android/i.test(navigator.userAgent) || /iPhone|iPad|iPod/i.test(navigator.userAgent)
131
+ );
132
+ };
133
+ var copyArray = function copyArray(source, dest) {
134
+ for (var i = 0, n = source.length; i < n; i++) {
135
+ dest[i] = source[i];
136
+ }
137
+ };
138
+ var extend = function extend(dest, src) {
139
+ for (var key in src) {
140
+ if (src.hasOwnProperty(key)) {
141
+ dest[key] = src[key];
142
+ }
143
+ }
144
+ return dest;
145
+ };
146
+
147
+ var cardboardVrDisplay = createCommonjsModule(function (module, exports) {
148
+ /**
149
+ * @license
150
+ * cardboard-vr-display
151
+ * Copyright (c) 2015-2017 Google
152
+ * Licensed under the Apache License, Version 2.0 (the "License");
153
+ * you may not use this file except in compliance with the License.
154
+ * You may obtain a copy of the License at
155
+ *
156
+ * http://www.apache.org/licenses/LICENSE-2.0
157
+ *
158
+ * Unless required by applicable law or agreed to in writing, software
159
+ * distributed under the License is distributed on an "AS IS" BASIS,
160
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
161
+ * See the License for the specific language governing permissions and
162
+ * limitations under the License.
163
+ */
164
+ /**
165
+ * @license
166
+ * gl-preserve-state
167
+ * Copyright (c) 2016, Brandon Jones.
168
+ *
169
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
170
+ * of this software and associated documentation files (the "Software"), to deal
171
+ * in the Software without restriction, including without limitation the rights
172
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
173
+ * copies of the Software, and to permit persons to whom the Software is
174
+ * furnished to do so, subject to the following conditions:
175
+ *
176
+ * The above copyright notice and this permission notice shall be included in
177
+ * all copies or substantial portions of the Software.
178
+ *
179
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
180
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
181
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
182
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
183
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
184
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
185
+ * THE SOFTWARE.
186
+ */
187
+ /**
188
+ * @license
189
+ * webvr-polyfill-dpdb
190
+ * Copyright (c) 2015-2017 Google
191
+ * Licensed under the Apache License, Version 2.0 (the "License");
192
+ * you may not use this file except in compliance with the License.
193
+ * You may obtain a copy of the License at
194
+ *
195
+ * http://www.apache.org/licenses/LICENSE-2.0
196
+ *
197
+ * Unless required by applicable law or agreed to in writing, software
198
+ * distributed under the License is distributed on an "AS IS" BASIS,
199
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ * See the License for the specific language governing permissions and
201
+ * limitations under the License.
202
+ */
203
+ /**
204
+ * @license
205
+ * nosleep.js
206
+ * Copyright (c) 2017, Rich Tibbett
207
+ *
208
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
209
+ * of this software and associated documentation files (the "Software"), to deal
210
+ * in the Software without restriction, including without limitation the rights
211
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
212
+ * copies of the Software, and to permit persons to whom the Software is
213
+ * furnished to do so, subject to the following conditions:
214
+ *
215
+ * The above copyright notice and this permission notice shall be included in
216
+ * all copies or substantial portions of the Software.
217
+ *
218
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
219
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
220
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
221
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
222
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
223
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
224
+ * THE SOFTWARE.
225
+ */
226
+ (function (global, factory) {
227
+ module.exports = factory();
228
+ }(commonjsGlobal, (function () { var classCallCheck = function (instance, Constructor) {
229
+ if (!(instance instanceof Constructor)) {
230
+ throw new TypeError("Cannot call a class as a function");
231
+ }
232
+ };
233
+ var createClass = function () {
234
+ function defineProperties(target, props) {
235
+ for (var i = 0; i < props.length; i++) {
236
+ var descriptor = props[i];
237
+ descriptor.enumerable = descriptor.enumerable || false;
238
+ descriptor.configurable = true;
239
+ if ("value" in descriptor) descriptor.writable = true;
240
+ Object.defineProperty(target, descriptor.key, descriptor);
241
+ }
242
+ }
243
+ return function (Constructor, protoProps, staticProps) {
244
+ if (protoProps) defineProperties(Constructor.prototype, protoProps);
245
+ if (staticProps) defineProperties(Constructor, staticProps);
246
+ return Constructor;
247
+ };
248
+ }();
249
+ var slicedToArray = function () {
250
+ function sliceIterator(arr, i) {
251
+ var _arr = [];
252
+ var _n = true;
253
+ var _d = false;
254
+ var _e = undefined;
255
+ try {
256
+ for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
257
+ _arr.push(_s.value);
258
+ if (i && _arr.length === i) break;
259
+ }
260
+ } catch (err) {
261
+ _d = true;
262
+ _e = err;
263
+ } finally {
264
+ try {
265
+ if (!_n && _i["return"]) _i["return"]();
266
+ } finally {
267
+ if (_d) throw _e;
268
+ }
269
+ }
270
+ return _arr;
271
+ }
272
+ return function (arr, i) {
273
+ if (Array.isArray(arr)) {
274
+ return arr;
275
+ } else if (Symbol.iterator in Object(arr)) {
276
+ return sliceIterator(arr, i);
277
+ } else {
278
+ throw new TypeError("Invalid attempt to destructure non-iterable instance");
279
+ }
280
+ };
281
+ }();
282
+ var MIN_TIMESTEP = 0.001;
283
+ var MAX_TIMESTEP = 1;
284
+ var base64 = function base64(mimeType, _base) {
285
+ return 'data:' + mimeType + ';base64,' + _base;
286
+ };
287
+ var lerp = function lerp(a, b, t) {
288
+ return a + (b - a) * t;
289
+ };
290
+ var isIOS = function () {
291
+ var isIOS = /iPad|iPhone|iPod/.test(navigator.platform);
292
+ return function () {
293
+ return isIOS;
294
+ };
295
+ }();
296
+ var isWebViewAndroid = function () {
297
+ var isWebViewAndroid = navigator.userAgent.indexOf('Version') !== -1 && navigator.userAgent.indexOf('Android') !== -1 && navigator.userAgent.indexOf('Chrome') !== -1;
298
+ return function () {
299
+ return isWebViewAndroid;
300
+ };
301
+ }();
302
+ var isSafari = function () {
303
+ var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
304
+ return function () {
305
+ return isSafari;
306
+ };
307
+ }();
308
+ var isFirefoxAndroid = function () {
309
+ var isFirefoxAndroid = navigator.userAgent.indexOf('Firefox') !== -1 && navigator.userAgent.indexOf('Android') !== -1;
310
+ return function () {
311
+ return isFirefoxAndroid;
312
+ };
313
+ }();
314
+ var getChromeVersion = function () {
315
+ var match = navigator.userAgent.match(/.*Chrome\/([0-9]+)/);
316
+ var value = match ? parseInt(match[1], 10) : null;
317
+ return function () {
318
+ return value;
319
+ };
320
+ }();
321
+ var isChromeWithoutDeviceMotion = function () {
322
+ var value = false;
323
+ if (getChromeVersion() === 65) {
324
+ var match = navigator.userAgent.match(/.*Chrome\/([0-9\.]*)/);
325
+ if (match) {
326
+ var _match$1$split = match[1].split('.'),
327
+ _match$1$split2 = slicedToArray(_match$1$split, 4),
328
+ major = _match$1$split2[0],
329
+ minor = _match$1$split2[1],
330
+ branch = _match$1$split2[2],
331
+ build = _match$1$split2[3];
332
+ value = parseInt(branch, 10) === 3325 && parseInt(build, 10) < 148;
333
+ }
334
+ }
335
+ return function () {
336
+ return value;
337
+ };
338
+ }();
339
+ var isR7 = function () {
340
+ var isR7 = navigator.userAgent.indexOf('R7 Build') !== -1;
341
+ return function () {
342
+ return isR7;
343
+ };
344
+ }();
345
+ var isLandscapeMode = function isLandscapeMode() {
346
+ var rtn = window.orientation == 90 || window.orientation == -90;
347
+ return isR7() ? !rtn : rtn;
348
+ };
349
+ var isTimestampDeltaValid = function isTimestampDeltaValid(timestampDeltaS) {
350
+ if (isNaN(timestampDeltaS)) {
351
+ return false;
352
+ }
353
+ if (timestampDeltaS <= MIN_TIMESTEP) {
354
+ return false;
355
+ }
356
+ if (timestampDeltaS > MAX_TIMESTEP) {
357
+ return false;
358
+ }
359
+ return true;
360
+ };
361
+ var getScreenWidth = function getScreenWidth() {
362
+ return Math.max(window.screen.width, window.screen.height) * window.devicePixelRatio;
363
+ };
364
+ var getScreenHeight = function getScreenHeight() {
365
+ return Math.min(window.screen.width, window.screen.height) * window.devicePixelRatio;
366
+ };
367
+ var requestFullscreen = function requestFullscreen(element) {
368
+ if (isWebViewAndroid()) {
369
+ return false;
370
+ }
371
+ if (element.requestFullscreen) {
372
+ element.requestFullscreen();
373
+ } else if (element.webkitRequestFullscreen) {
374
+ element.webkitRequestFullscreen();
375
+ } else if (element.mozRequestFullScreen) {
376
+ element.mozRequestFullScreen();
377
+ } else if (element.msRequestFullscreen) {
378
+ element.msRequestFullscreen();
379
+ } else {
380
+ return false;
381
+ }
382
+ return true;
383
+ };
384
+ var exitFullscreen = function exitFullscreen() {
385
+ if (document.exitFullscreen) {
386
+ document.exitFullscreen();
387
+ } else if (document.webkitExitFullscreen) {
388
+ document.webkitExitFullscreen();
389
+ } else if (document.mozCancelFullScreen) {
390
+ document.mozCancelFullScreen();
391
+ } else if (document.msExitFullscreen) {
392
+ document.msExitFullscreen();
393
+ } else {
394
+ return false;
395
+ }
396
+ return true;
397
+ };
398
+ var getFullscreenElement = function getFullscreenElement() {
399
+ return document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement;
400
+ };
401
+ var linkProgram = function linkProgram(gl, vertexSource, fragmentSource, attribLocationMap) {
402
+ var vertexShader = gl.createShader(gl.VERTEX_SHADER);
403
+ gl.shaderSource(vertexShader, vertexSource);
404
+ gl.compileShader(vertexShader);
405
+ var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
406
+ gl.shaderSource(fragmentShader, fragmentSource);
407
+ gl.compileShader(fragmentShader);
408
+ var program = gl.createProgram();
409
+ gl.attachShader(program, vertexShader);
410
+ gl.attachShader(program, fragmentShader);
411
+ for (var attribName in attribLocationMap) {
412
+ gl.bindAttribLocation(program, attribLocationMap[attribName], attribName);
413
+ }gl.linkProgram(program);
414
+ gl.deleteShader(vertexShader);
415
+ gl.deleteShader(fragmentShader);
416
+ return program;
417
+ };
418
+ var getProgramUniforms = function getProgramUniforms(gl, program) {
419
+ var uniforms = {};
420
+ var uniformCount = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
421
+ var uniformName = '';
422
+ for (var i = 0; i < uniformCount; i++) {
423
+ var uniformInfo = gl.getActiveUniform(program, i);
424
+ uniformName = uniformInfo.name.replace('[0]', '');
425
+ uniforms[uniformName] = gl.getUniformLocation(program, uniformName);
426
+ }
427
+ return uniforms;
428
+ };
429
+ var orthoMatrix = function orthoMatrix(out, left, right, bottom, top, near, far) {
430
+ var lr = 1 / (left - right),
431
+ bt = 1 / (bottom - top),
432
+ nf = 1 / (near - far);
433
+ out[0] = -2 * lr;
434
+ out[1] = 0;
435
+ out[2] = 0;
436
+ out[3] = 0;
437
+ out[4] = 0;
438
+ out[5] = -2 * bt;
439
+ out[6] = 0;
440
+ out[7] = 0;
441
+ out[8] = 0;
442
+ out[9] = 0;
443
+ out[10] = 2 * nf;
444
+ out[11] = 0;
445
+ out[12] = (left + right) * lr;
446
+ out[13] = (top + bottom) * bt;
447
+ out[14] = (far + near) * nf;
448
+ out[15] = 1;
449
+ return out;
450
+ };
451
+ var isMobile = function isMobile() {
452
+ var check = false;
453
+ (function (a) {
454
+ if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4))) check = true;
455
+ })(navigator.userAgent || navigator.vendor || window.opera);
456
+ return check;
457
+ };
458
+ var extend = function extend(dest, src) {
459
+ for (var key in src) {
460
+ if (src.hasOwnProperty(key)) {
461
+ dest[key] = src[key];
462
+ }
463
+ }
464
+ return dest;
465
+ };
466
+ var safariCssSizeWorkaround = function safariCssSizeWorkaround(canvas) {
467
+ if (isIOS()) {
468
+ var width = canvas.style.width;
469
+ var height = canvas.style.height;
470
+ canvas.style.width = parseInt(width) + 1 + 'px';
471
+ canvas.style.height = parseInt(height) + 'px';
472
+ setTimeout(function () {
473
+ canvas.style.width = width;
474
+ canvas.style.height = height;
475
+ }, 100);
476
+ }
477
+ window.canvas = canvas;
478
+ };
479
+ var frameDataFromPose = function () {
480
+ var piOver180 = Math.PI / 180.0;
481
+ var rad45 = Math.PI * 0.25;
482
+ function mat4_perspectiveFromFieldOfView(out, fov, near, far) {
483
+ var upTan = Math.tan(fov ? fov.upDegrees * piOver180 : rad45),
484
+ downTan = Math.tan(fov ? fov.downDegrees * piOver180 : rad45),
485
+ leftTan = Math.tan(fov ? fov.leftDegrees * piOver180 : rad45),
486
+ rightTan = Math.tan(fov ? fov.rightDegrees * piOver180 : rad45),
487
+ xScale = 2.0 / (leftTan + rightTan),
488
+ yScale = 2.0 / (upTan + downTan);
489
+ out[0] = xScale;
490
+ out[1] = 0.0;
491
+ out[2] = 0.0;
492
+ out[3] = 0.0;
493
+ out[4] = 0.0;
494
+ out[5] = yScale;
495
+ out[6] = 0.0;
496
+ out[7] = 0.0;
497
+ out[8] = -((leftTan - rightTan) * xScale * 0.5);
498
+ out[9] = (upTan - downTan) * yScale * 0.5;
499
+ out[10] = far / (near - far);
500
+ out[11] = -1.0;
501
+ out[12] = 0.0;
502
+ out[13] = 0.0;
503
+ out[14] = far * near / (near - far);
504
+ out[15] = 0.0;
505
+ return out;
506
+ }
507
+ function mat4_fromRotationTranslation(out, q, v) {
508
+ var x = q[0],
509
+ y = q[1],
510
+ z = q[2],
511
+ w = q[3],
512
+ x2 = x + x,
513
+ y2 = y + y,
514
+ z2 = z + z,
515
+ xx = x * x2,
516
+ xy = x * y2,
517
+ xz = x * z2,
518
+ yy = y * y2,
519
+ yz = y * z2,
520
+ zz = z * z2,
521
+ wx = w * x2,
522
+ wy = w * y2,
523
+ wz = w * z2;
524
+ out[0] = 1 - (yy + zz);
525
+ out[1] = xy + wz;
526
+ out[2] = xz - wy;
527
+ out[3] = 0;
528
+ out[4] = xy - wz;
529
+ out[5] = 1 - (xx + zz);
530
+ out[6] = yz + wx;
531
+ out[7] = 0;
532
+ out[8] = xz + wy;
533
+ out[9] = yz - wx;
534
+ out[10] = 1 - (xx + yy);
535
+ out[11] = 0;
536
+ out[12] = v[0];
537
+ out[13] = v[1];
538
+ out[14] = v[2];
539
+ out[15] = 1;
540
+ return out;
541
+ }
542
+ function mat4_translate(out, a, v) {
543
+ var x = v[0],
544
+ y = v[1],
545
+ z = v[2],
546
+ a00,
547
+ a01,
548
+ a02,
549
+ a03,
550
+ a10,
551
+ a11,
552
+ a12,
553
+ a13,
554
+ a20,
555
+ a21,
556
+ a22,
557
+ a23;
558
+ if (a === out) {
559
+ out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];
560
+ out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];
561
+ out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];
562
+ out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];
563
+ } else {
564
+ a00 = a[0];a01 = a[1];a02 = a[2];a03 = a[3];
565
+ a10 = a[4];a11 = a[5];a12 = a[6];a13 = a[7];
566
+ a20 = a[8];a21 = a[9];a22 = a[10];a23 = a[11];
567
+ out[0] = a00;out[1] = a01;out[2] = a02;out[3] = a03;
568
+ out[4] = a10;out[5] = a11;out[6] = a12;out[7] = a13;
569
+ out[8] = a20;out[9] = a21;out[10] = a22;out[11] = a23;
570
+ out[12] = a00 * x + a10 * y + a20 * z + a[12];
571
+ out[13] = a01 * x + a11 * y + a21 * z + a[13];
572
+ out[14] = a02 * x + a12 * y + a22 * z + a[14];
573
+ out[15] = a03 * x + a13 * y + a23 * z + a[15];
574
+ }
575
+ return out;
576
+ }
577
+ function mat4_invert(out, a) {
578
+ var a00 = a[0],
579
+ a01 = a[1],
580
+ a02 = a[2],
581
+ a03 = a[3],
582
+ a10 = a[4],
583
+ a11 = a[5],
584
+ a12 = a[6],
585
+ a13 = a[7],
586
+ a20 = a[8],
587
+ a21 = a[9],
588
+ a22 = a[10],
589
+ a23 = a[11],
590
+ a30 = a[12],
591
+ a31 = a[13],
592
+ a32 = a[14],
593
+ a33 = a[15],
594
+ b00 = a00 * a11 - a01 * a10,
595
+ b01 = a00 * a12 - a02 * a10,
596
+ b02 = a00 * a13 - a03 * a10,
597
+ b03 = a01 * a12 - a02 * a11,
598
+ b04 = a01 * a13 - a03 * a11,
599
+ b05 = a02 * a13 - a03 * a12,
600
+ b06 = a20 * a31 - a21 * a30,
601
+ b07 = a20 * a32 - a22 * a30,
602
+ b08 = a20 * a33 - a23 * a30,
603
+ b09 = a21 * a32 - a22 * a31,
604
+ b10 = a21 * a33 - a23 * a31,
605
+ b11 = a22 * a33 - a23 * a32,
606
+ det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
607
+ if (!det) {
608
+ return null;
609
+ }
610
+ det = 1.0 / det;
611
+ out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
612
+ out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
613
+ out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
614
+ out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
615
+ out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
616
+ out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
617
+ out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
618
+ out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
619
+ out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
620
+ out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
621
+ out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
622
+ out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
623
+ out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
624
+ out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
625
+ out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
626
+ out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
627
+ return out;
628
+ }
629
+ var defaultOrientation = new Float32Array([0, 0, 0, 1]);
630
+ var defaultPosition = new Float32Array([0, 0, 0]);
631
+ function updateEyeMatrices(projection, view, pose, fov, offset, vrDisplay) {
632
+ mat4_perspectiveFromFieldOfView(projection, fov || null, vrDisplay.depthNear, vrDisplay.depthFar);
633
+ var orientation = pose.orientation || defaultOrientation;
634
+ var position = pose.position || defaultPosition;
635
+ mat4_fromRotationTranslation(view, orientation, position);
636
+ if (offset) mat4_translate(view, view, offset);
637
+ mat4_invert(view, view);
638
+ }
639
+ return function (frameData, pose, vrDisplay) {
640
+ if (!frameData || !pose) return false;
641
+ frameData.pose = pose;
642
+ frameData.timestamp = pose.timestamp;
643
+ updateEyeMatrices(frameData.leftProjectionMatrix, frameData.leftViewMatrix, pose, vrDisplay._getFieldOfView("left"), vrDisplay._getEyeOffset("left"), vrDisplay);
644
+ updateEyeMatrices(frameData.rightProjectionMatrix, frameData.rightViewMatrix, pose, vrDisplay._getFieldOfView("right"), vrDisplay._getEyeOffset("right"), vrDisplay);
645
+ return true;
646
+ };
647
+ }();
648
+ var isInsideCrossOriginIFrame = function isInsideCrossOriginIFrame() {
649
+ var isFramed = window.self !== window.top;
650
+ var refOrigin = getOriginFromUrl(document.referrer);
651
+ var thisOrigin = getOriginFromUrl(window.location.href);
652
+ return isFramed && refOrigin !== thisOrigin;
653
+ };
654
+ var getOriginFromUrl = function getOriginFromUrl(url) {
655
+ var domainIdx;
656
+ var protoSepIdx = url.indexOf("://");
657
+ if (protoSepIdx !== -1) {
658
+ domainIdx = protoSepIdx + 3;
659
+ } else {
660
+ domainIdx = 0;
661
+ }
662
+ var domainEndIdx = url.indexOf('/', domainIdx);
663
+ if (domainEndIdx === -1) {
664
+ domainEndIdx = url.length;
665
+ }
666
+ return url.substring(0, domainEndIdx);
667
+ };
668
+ var getQuaternionAngle = function getQuaternionAngle(quat) {
669
+ if (quat.w > 1) {
670
+ console.warn('getQuaternionAngle: w > 1');
671
+ return 0;
672
+ }
673
+ var angle = 2 * Math.acos(quat.w);
674
+ return angle;
675
+ };
676
+ var warnOnce = function () {
677
+ var observedWarnings = {};
678
+ return function (key, message) {
679
+ if (observedWarnings[key] === undefined) {
680
+ console.warn('webvr-polyfill: ' + message);
681
+ observedWarnings[key] = true;
682
+ }
683
+ };
684
+ }();
685
+ var deprecateWarning = function deprecateWarning(deprecated, suggested) {
686
+ var alternative = suggested ? 'Please use ' + suggested + ' instead.' : '';
687
+ warnOnce(deprecated, deprecated + ' has been deprecated. ' + 'This may not work on native WebVR displays. ' + alternative);
688
+ };
689
+ function WGLUPreserveGLState(gl, bindings, callback) {
690
+ if (!bindings) {
691
+ callback(gl);
692
+ return;
693
+ }
694
+ var boundValues = [];
695
+ var activeTexture = null;
696
+ for (var i = 0; i < bindings.length; ++i) {
697
+ var binding = bindings[i];
698
+ switch (binding) {
699
+ case gl.TEXTURE_BINDING_2D:
700
+ case gl.TEXTURE_BINDING_CUBE_MAP:
701
+ var textureUnit = bindings[++i];
702
+ if (textureUnit < gl.TEXTURE0 || textureUnit > gl.TEXTURE31) {
703
+ console.error("TEXTURE_BINDING_2D or TEXTURE_BINDING_CUBE_MAP must be followed by a valid texture unit");
704
+ boundValues.push(null, null);
705
+ break;
706
+ }
707
+ if (!activeTexture) {
708
+ activeTexture = gl.getParameter(gl.ACTIVE_TEXTURE);
709
+ }
710
+ gl.activeTexture(textureUnit);
711
+ boundValues.push(gl.getParameter(binding), null);
712
+ break;
713
+ case gl.ACTIVE_TEXTURE:
714
+ activeTexture = gl.getParameter(gl.ACTIVE_TEXTURE);
715
+ boundValues.push(null);
716
+ break;
717
+ default:
718
+ boundValues.push(gl.getParameter(binding));
719
+ break;
720
+ }
721
+ }
722
+ callback(gl);
723
+ for (var i = 0; i < bindings.length; ++i) {
724
+ var binding = bindings[i];
725
+ var boundValue = boundValues[i];
726
+ switch (binding) {
727
+ case gl.ACTIVE_TEXTURE:
728
+ break;
729
+ case gl.ARRAY_BUFFER_BINDING:
730
+ gl.bindBuffer(gl.ARRAY_BUFFER, boundValue);
731
+ break;
732
+ case gl.COLOR_CLEAR_VALUE:
733
+ gl.clearColor(boundValue[0], boundValue[1], boundValue[2], boundValue[3]);
734
+ break;
735
+ case gl.COLOR_WRITEMASK:
736
+ gl.colorMask(boundValue[0], boundValue[1], boundValue[2], boundValue[3]);
737
+ break;
738
+ case gl.CURRENT_PROGRAM:
739
+ gl.useProgram(boundValue);
740
+ break;
741
+ case gl.ELEMENT_ARRAY_BUFFER_BINDING:
742
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, boundValue);
743
+ break;
744
+ case gl.FRAMEBUFFER_BINDING:
745
+ gl.bindFramebuffer(gl.FRAMEBUFFER, boundValue);
746
+ break;
747
+ case gl.RENDERBUFFER_BINDING:
748
+ gl.bindRenderbuffer(gl.RENDERBUFFER, boundValue);
749
+ break;
750
+ case gl.TEXTURE_BINDING_2D:
751
+ var textureUnit = bindings[++i];
752
+ if (textureUnit < gl.TEXTURE0 || textureUnit > gl.TEXTURE31)
753
+ break;
754
+ gl.activeTexture(textureUnit);
755
+ gl.bindTexture(gl.TEXTURE_2D, boundValue);
756
+ break;
757
+ case gl.TEXTURE_BINDING_CUBE_MAP:
758
+ var textureUnit = bindings[++i];
759
+ if (textureUnit < gl.TEXTURE0 || textureUnit > gl.TEXTURE31)
760
+ break;
761
+ gl.activeTexture(textureUnit);
762
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, boundValue);
763
+ break;
764
+ case gl.VIEWPORT:
765
+ gl.viewport(boundValue[0], boundValue[1], boundValue[2], boundValue[3]);
766
+ break;
767
+ case gl.BLEND:
768
+ case gl.CULL_FACE:
769
+ case gl.DEPTH_TEST:
770
+ case gl.SCISSOR_TEST:
771
+ case gl.STENCIL_TEST:
772
+ if (boundValue) {
773
+ gl.enable(binding);
774
+ } else {
775
+ gl.disable(binding);
776
+ }
777
+ break;
778
+ default:
779
+ console.log("No GL restore behavior for 0x" + binding.toString(16));
780
+ break;
781
+ }
782
+ if (activeTexture) {
783
+ gl.activeTexture(activeTexture);
784
+ }
785
+ }
786
+ }
787
+ var glPreserveState = WGLUPreserveGLState;
788
+ var distortionVS = ['attribute vec2 position;', 'attribute vec3 texCoord;', 'varying vec2 vTexCoord;', 'uniform vec4 viewportOffsetScale[2];', 'void main() {', ' vec4 viewport = viewportOffsetScale[int(texCoord.z)];', ' vTexCoord = (texCoord.xy * viewport.zw) + viewport.xy;', ' gl_Position = vec4( position, 1.0, 1.0 );', '}'].join('\n');
789
+ var distortionFS = ['precision mediump float;', 'uniform sampler2D diffuse;', 'varying vec2 vTexCoord;', 'void main() {', ' gl_FragColor = texture2D(diffuse, vTexCoord);', '}'].join('\n');
790
+ function CardboardDistorter(gl, cardboardUI, bufferScale, dirtySubmitFrameBindings) {
791
+ this.gl = gl;
792
+ this.cardboardUI = cardboardUI;
793
+ this.bufferScale = bufferScale;
794
+ this.dirtySubmitFrameBindings = dirtySubmitFrameBindings;
795
+ this.ctxAttribs = gl.getContextAttributes();
796
+ this.meshWidth = 20;
797
+ this.meshHeight = 20;
798
+ this.bufferWidth = gl.drawingBufferWidth;
799
+ this.bufferHeight = gl.drawingBufferHeight;
800
+ this.realBindFramebuffer = gl.bindFramebuffer;
801
+ this.realEnable = gl.enable;
802
+ this.realDisable = gl.disable;
803
+ this.realColorMask = gl.colorMask;
804
+ this.realClearColor = gl.clearColor;
805
+ this.realViewport = gl.viewport;
806
+ if (!isIOS()) {
807
+ this.realCanvasWidth = Object.getOwnPropertyDescriptor(gl.canvas.__proto__, 'width');
808
+ this.realCanvasHeight = Object.getOwnPropertyDescriptor(gl.canvas.__proto__, 'height');
809
+ }
810
+ this.isPatched = false;
811
+ this.lastBoundFramebuffer = null;
812
+ this.cullFace = false;
813
+ this.depthTest = false;
814
+ this.blend = false;
815
+ this.scissorTest = false;
816
+ this.stencilTest = false;
817
+ this.viewport = [0, 0, 0, 0];
818
+ this.colorMask = [true, true, true, true];
819
+ this.clearColor = [0, 0, 0, 0];
820
+ this.attribs = {
821
+ position: 0,
822
+ texCoord: 1
823
+ };
824
+ this.program = linkProgram(gl, distortionVS, distortionFS, this.attribs);
825
+ this.uniforms = getProgramUniforms(gl, this.program);
826
+ this.viewportOffsetScale = new Float32Array(8);
827
+ this.setTextureBounds();
828
+ this.vertexBuffer = gl.createBuffer();
829
+ this.indexBuffer = gl.createBuffer();
830
+ this.indexCount = 0;
831
+ this.renderTarget = gl.createTexture();
832
+ this.framebuffer = gl.createFramebuffer();
833
+ this.depthStencilBuffer = null;
834
+ this.depthBuffer = null;
835
+ this.stencilBuffer = null;
836
+ if (this.ctxAttribs.depth && this.ctxAttribs.stencil) {
837
+ this.depthStencilBuffer = gl.createRenderbuffer();
838
+ } else if (this.ctxAttribs.depth) {
839
+ this.depthBuffer = gl.createRenderbuffer();
840
+ } else if (this.ctxAttribs.stencil) {
841
+ this.stencilBuffer = gl.createRenderbuffer();
842
+ }
843
+ this.patch();
844
+ this.onResize();
845
+ }
846
+ CardboardDistorter.prototype.destroy = function () {
847
+ var gl = this.gl;
848
+ this.unpatch();
849
+ gl.deleteProgram(this.program);
850
+ gl.deleteBuffer(this.vertexBuffer);
851
+ gl.deleteBuffer(this.indexBuffer);
852
+ gl.deleteTexture(this.renderTarget);
853
+ gl.deleteFramebuffer(this.framebuffer);
854
+ if (this.depthStencilBuffer) {
855
+ gl.deleteRenderbuffer(this.depthStencilBuffer);
856
+ }
857
+ if (this.depthBuffer) {
858
+ gl.deleteRenderbuffer(this.depthBuffer);
859
+ }
860
+ if (this.stencilBuffer) {
861
+ gl.deleteRenderbuffer(this.stencilBuffer);
862
+ }
863
+ if (this.cardboardUI) {
864
+ this.cardboardUI.destroy();
865
+ }
866
+ };
867
+ CardboardDistorter.prototype.onResize = function () {
868
+ var gl = this.gl;
869
+ var self = this;
870
+ var glState = [gl.RENDERBUFFER_BINDING, gl.TEXTURE_BINDING_2D, gl.TEXTURE0];
871
+ glPreserveState(gl, glState, function (gl) {
872
+ self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, null);
873
+ if (self.scissorTest) {
874
+ self.realDisable.call(gl, gl.SCISSOR_TEST);
875
+ }
876
+ self.realColorMask.call(gl, true, true, true, true);
877
+ self.realViewport.call(gl, 0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
878
+ self.realClearColor.call(gl, 0, 0, 0, 1);
879
+ gl.clear(gl.COLOR_BUFFER_BIT);
880
+ self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, self.framebuffer);
881
+ gl.bindTexture(gl.TEXTURE_2D, self.renderTarget);
882
+ gl.texImage2D(gl.TEXTURE_2D, 0, self.ctxAttribs.alpha ? gl.RGBA : gl.RGB, self.bufferWidth, self.bufferHeight, 0, self.ctxAttribs.alpha ? gl.RGBA : gl.RGB, gl.UNSIGNED_BYTE, null);
883
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
884
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
885
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
886
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
887
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, self.renderTarget, 0);
888
+ if (self.ctxAttribs.depth && self.ctxAttribs.stencil) {
889
+ gl.bindRenderbuffer(gl.RENDERBUFFER, self.depthStencilBuffer);
890
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, self.bufferWidth, self.bufferHeight);
891
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, self.depthStencilBuffer);
892
+ } else if (self.ctxAttribs.depth) {
893
+ gl.bindRenderbuffer(gl.RENDERBUFFER, self.depthBuffer);
894
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, self.bufferWidth, self.bufferHeight);
895
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, self.depthBuffer);
896
+ } else if (self.ctxAttribs.stencil) {
897
+ gl.bindRenderbuffer(gl.RENDERBUFFER, self.stencilBuffer);
898
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.STENCIL_INDEX8, self.bufferWidth, self.bufferHeight);
899
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, self.stencilBuffer);
900
+ }
901
+ if (!gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE) {
902
+ console.error('Framebuffer incomplete!');
903
+ }
904
+ self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, self.lastBoundFramebuffer);
905
+ if (self.scissorTest) {
906
+ self.realEnable.call(gl, gl.SCISSOR_TEST);
907
+ }
908
+ self.realColorMask.apply(gl, self.colorMask);
909
+ self.realViewport.apply(gl, self.viewport);
910
+ self.realClearColor.apply(gl, self.clearColor);
911
+ });
912
+ if (this.cardboardUI) {
913
+ this.cardboardUI.onResize();
914
+ }
915
+ };
916
+ CardboardDistorter.prototype.patch = function () {
917
+ if (this.isPatched) {
918
+ return;
919
+ }
920
+ var self = this;
921
+ var canvas = this.gl.canvas;
922
+ var gl = this.gl;
923
+ if (!isIOS()) {
924
+ canvas.width = getScreenWidth() * this.bufferScale;
925
+ canvas.height = getScreenHeight() * this.bufferScale;
926
+ Object.defineProperty(canvas, 'width', {
927
+ configurable: true,
928
+ enumerable: true,
929
+ get: function get() {
930
+ return self.bufferWidth;
931
+ },
932
+ set: function set(value) {
933
+ self.bufferWidth = value;
934
+ self.realCanvasWidth.set.call(canvas, value);
935
+ self.onResize();
936
+ }
937
+ });
938
+ Object.defineProperty(canvas, 'height', {
939
+ configurable: true,
940
+ enumerable: true,
941
+ get: function get() {
942
+ return self.bufferHeight;
943
+ },
944
+ set: function set(value) {
945
+ self.bufferHeight = value;
946
+ self.realCanvasHeight.set.call(canvas, value);
947
+ self.onResize();
948
+ }
949
+ });
950
+ }
951
+ this.lastBoundFramebuffer = gl.getParameter(gl.FRAMEBUFFER_BINDING);
952
+ if (this.lastBoundFramebuffer == null) {
953
+ this.lastBoundFramebuffer = this.framebuffer;
954
+ this.gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);
955
+ }
956
+ this.gl.bindFramebuffer = function (target, framebuffer) {
957
+ self.lastBoundFramebuffer = framebuffer ? framebuffer : self.framebuffer;
958
+ self.realBindFramebuffer.call(gl, target, self.lastBoundFramebuffer);
959
+ };
960
+ this.cullFace = gl.getParameter(gl.CULL_FACE);
961
+ this.depthTest = gl.getParameter(gl.DEPTH_TEST);
962
+ this.blend = gl.getParameter(gl.BLEND);
963
+ this.scissorTest = gl.getParameter(gl.SCISSOR_TEST);
964
+ this.stencilTest = gl.getParameter(gl.STENCIL_TEST);
965
+ gl.enable = function (pname) {
966
+ switch (pname) {
967
+ case gl.CULL_FACE:
968
+ self.cullFace = true;break;
969
+ case gl.DEPTH_TEST:
970
+ self.depthTest = true;break;
971
+ case gl.BLEND:
972
+ self.blend = true;break;
973
+ case gl.SCISSOR_TEST:
974
+ self.scissorTest = true;break;
975
+ case gl.STENCIL_TEST:
976
+ self.stencilTest = true;break;
977
+ }
978
+ self.realEnable.call(gl, pname);
979
+ };
980
+ gl.disable = function (pname) {
981
+ switch (pname) {
982
+ case gl.CULL_FACE:
983
+ self.cullFace = false;break;
984
+ case gl.DEPTH_TEST:
985
+ self.depthTest = false;break;
986
+ case gl.BLEND:
987
+ self.blend = false;break;
988
+ case gl.SCISSOR_TEST:
989
+ self.scissorTest = false;break;
990
+ case gl.STENCIL_TEST:
991
+ self.stencilTest = false;break;
992
+ }
993
+ self.realDisable.call(gl, pname);
994
+ };
995
+ this.colorMask = gl.getParameter(gl.COLOR_WRITEMASK);
996
+ gl.colorMask = function (r, g, b, a) {
997
+ self.colorMask[0] = r;
998
+ self.colorMask[1] = g;
999
+ self.colorMask[2] = b;
1000
+ self.colorMask[3] = a;
1001
+ self.realColorMask.call(gl, r, g, b, a);
1002
+ };
1003
+ this.clearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE);
1004
+ gl.clearColor = function (r, g, b, a) {
1005
+ self.clearColor[0] = r;
1006
+ self.clearColor[1] = g;
1007
+ self.clearColor[2] = b;
1008
+ self.clearColor[3] = a;
1009
+ self.realClearColor.call(gl, r, g, b, a);
1010
+ };
1011
+ this.viewport = gl.getParameter(gl.VIEWPORT);
1012
+ gl.viewport = function (x, y, w, h) {
1013
+ self.viewport[0] = x;
1014
+ self.viewport[1] = y;
1015
+ self.viewport[2] = w;
1016
+ self.viewport[3] = h;
1017
+ self.realViewport.call(gl, x, y, w, h);
1018
+ };
1019
+ this.isPatched = true;
1020
+ safariCssSizeWorkaround(canvas);
1021
+ };
1022
+ CardboardDistorter.prototype.unpatch = function () {
1023
+ if (!this.isPatched) {
1024
+ return;
1025
+ }
1026
+ var gl = this.gl;
1027
+ var canvas = this.gl.canvas;
1028
+ if (!isIOS()) {
1029
+ Object.defineProperty(canvas, 'width', this.realCanvasWidth);
1030
+ Object.defineProperty(canvas, 'height', this.realCanvasHeight);
1031
+ }
1032
+ canvas.width = this.bufferWidth;
1033
+ canvas.height = this.bufferHeight;
1034
+ gl.bindFramebuffer = this.realBindFramebuffer;
1035
+ gl.enable = this.realEnable;
1036
+ gl.disable = this.realDisable;
1037
+ gl.colorMask = this.realColorMask;
1038
+ gl.clearColor = this.realClearColor;
1039
+ gl.viewport = this.realViewport;
1040
+ if (this.lastBoundFramebuffer == this.framebuffer) {
1041
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
1042
+ }
1043
+ this.isPatched = false;
1044
+ setTimeout(function () {
1045
+ safariCssSizeWorkaround(canvas);
1046
+ }, 1);
1047
+ };
1048
+ CardboardDistorter.prototype.setTextureBounds = function (leftBounds, rightBounds) {
1049
+ if (!leftBounds) {
1050
+ leftBounds = [0, 0, 0.5, 1];
1051
+ }
1052
+ if (!rightBounds) {
1053
+ rightBounds = [0.5, 0, 0.5, 1];
1054
+ }
1055
+ this.viewportOffsetScale[0] = leftBounds[0];
1056
+ this.viewportOffsetScale[1] = leftBounds[1];
1057
+ this.viewportOffsetScale[2] = leftBounds[2];
1058
+ this.viewportOffsetScale[3] = leftBounds[3];
1059
+ this.viewportOffsetScale[4] = rightBounds[0];
1060
+ this.viewportOffsetScale[5] = rightBounds[1];
1061
+ this.viewportOffsetScale[6] = rightBounds[2];
1062
+ this.viewportOffsetScale[7] = rightBounds[3];
1063
+ };
1064
+ CardboardDistorter.prototype.submitFrame = function () {
1065
+ var gl = this.gl;
1066
+ var self = this;
1067
+ var glState = [];
1068
+ if (!this.dirtySubmitFrameBindings) {
1069
+ glState.push(gl.CURRENT_PROGRAM, gl.ARRAY_BUFFER_BINDING, gl.ELEMENT_ARRAY_BUFFER_BINDING, gl.TEXTURE_BINDING_2D, gl.TEXTURE0);
1070
+ }
1071
+ glPreserveState(gl, glState, function (gl) {
1072
+ self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, null);
1073
+ if (self.cullFace) {
1074
+ self.realDisable.call(gl, gl.CULL_FACE);
1075
+ }
1076
+ if (self.depthTest) {
1077
+ self.realDisable.call(gl, gl.DEPTH_TEST);
1078
+ }
1079
+ if (self.blend) {
1080
+ self.realDisable.call(gl, gl.BLEND);
1081
+ }
1082
+ if (self.scissorTest) {
1083
+ self.realDisable.call(gl, gl.SCISSOR_TEST);
1084
+ }
1085
+ if (self.stencilTest) {
1086
+ self.realDisable.call(gl, gl.STENCIL_TEST);
1087
+ }
1088
+ self.realColorMask.call(gl, true, true, true, true);
1089
+ self.realViewport.call(gl, 0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
1090
+ if (self.ctxAttribs.alpha || isIOS()) {
1091
+ self.realClearColor.call(gl, 0, 0, 0, 1);
1092
+ gl.clear(gl.COLOR_BUFFER_BIT);
1093
+ }
1094
+ gl.useProgram(self.program);
1095
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, self.indexBuffer);
1096
+ gl.bindBuffer(gl.ARRAY_BUFFER, self.vertexBuffer);
1097
+ gl.enableVertexAttribArray(self.attribs.position);
1098
+ gl.enableVertexAttribArray(self.attribs.texCoord);
1099
+ gl.vertexAttribPointer(self.attribs.position, 2, gl.FLOAT, false, 20, 0);
1100
+ gl.vertexAttribPointer(self.attribs.texCoord, 3, gl.FLOAT, false, 20, 8);
1101
+ gl.activeTexture(gl.TEXTURE0);
1102
+ gl.uniform1i(self.uniforms.diffuse, 0);
1103
+ gl.bindTexture(gl.TEXTURE_2D, self.renderTarget);
1104
+ gl.uniform4fv(self.uniforms.viewportOffsetScale, self.viewportOffsetScale);
1105
+ gl.drawElements(gl.TRIANGLES, self.indexCount, gl.UNSIGNED_SHORT, 0);
1106
+ if (self.cardboardUI) {
1107
+ self.cardboardUI.renderNoState();
1108
+ }
1109
+ self.realBindFramebuffer.call(self.gl, gl.FRAMEBUFFER, self.framebuffer);
1110
+ if (!self.ctxAttribs.preserveDrawingBuffer) {
1111
+ self.realClearColor.call(gl, 0, 0, 0, 0);
1112
+ gl.clear(gl.COLOR_BUFFER_BIT);
1113
+ }
1114
+ if (!self.dirtySubmitFrameBindings) {
1115
+ self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, self.lastBoundFramebuffer);
1116
+ }
1117
+ if (self.cullFace) {
1118
+ self.realEnable.call(gl, gl.CULL_FACE);
1119
+ }
1120
+ if (self.depthTest) {
1121
+ self.realEnable.call(gl, gl.DEPTH_TEST);
1122
+ }
1123
+ if (self.blend) {
1124
+ self.realEnable.call(gl, gl.BLEND);
1125
+ }
1126
+ if (self.scissorTest) {
1127
+ self.realEnable.call(gl, gl.SCISSOR_TEST);
1128
+ }
1129
+ if (self.stencilTest) {
1130
+ self.realEnable.call(gl, gl.STENCIL_TEST);
1131
+ }
1132
+ self.realColorMask.apply(gl, self.colorMask);
1133
+ self.realViewport.apply(gl, self.viewport);
1134
+ if (self.ctxAttribs.alpha || !self.ctxAttribs.preserveDrawingBuffer) {
1135
+ self.realClearColor.apply(gl, self.clearColor);
1136
+ }
1137
+ });
1138
+ if (isIOS()) {
1139
+ var canvas = gl.canvas;
1140
+ if (canvas.width != self.bufferWidth || canvas.height != self.bufferHeight) {
1141
+ self.bufferWidth = canvas.width;
1142
+ self.bufferHeight = canvas.height;
1143
+ self.onResize();
1144
+ }
1145
+ }
1146
+ };
1147
+ CardboardDistorter.prototype.updateDeviceInfo = function (deviceInfo) {
1148
+ var gl = this.gl;
1149
+ var self = this;
1150
+ var glState = [gl.ARRAY_BUFFER_BINDING, gl.ELEMENT_ARRAY_BUFFER_BINDING];
1151
+ glPreserveState(gl, glState, function (gl) {
1152
+ var vertices = self.computeMeshVertices_(self.meshWidth, self.meshHeight, deviceInfo);
1153
+ gl.bindBuffer(gl.ARRAY_BUFFER, self.vertexBuffer);
1154
+ gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
1155
+ if (!self.indexCount) {
1156
+ var indices = self.computeMeshIndices_(self.meshWidth, self.meshHeight);
1157
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, self.indexBuffer);
1158
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
1159
+ self.indexCount = indices.length;
1160
+ }
1161
+ });
1162
+ };
1163
+ CardboardDistorter.prototype.computeMeshVertices_ = function (width, height, deviceInfo) {
1164
+ var vertices = new Float32Array(2 * width * height * 5);
1165
+ var lensFrustum = deviceInfo.getLeftEyeVisibleTanAngles();
1166
+ var noLensFrustum = deviceInfo.getLeftEyeNoLensTanAngles();
1167
+ var viewport = deviceInfo.getLeftEyeVisibleScreenRect(noLensFrustum);
1168
+ var vidx = 0;
1169
+ for (var e = 0; e < 2; e++) {
1170
+ for (var j = 0; j < height; j++) {
1171
+ for (var i = 0; i < width; i++, vidx++) {
1172
+ var u = i / (width - 1);
1173
+ var v = j / (height - 1);
1174
+ var s = u;
1175
+ var t = v;
1176
+ var x = lerp(lensFrustum[0], lensFrustum[2], u);
1177
+ var y = lerp(lensFrustum[3], lensFrustum[1], v);
1178
+ var d = Math.sqrt(x * x + y * y);
1179
+ var r = deviceInfo.distortion.distortInverse(d);
1180
+ var p = x * r / d;
1181
+ var q = y * r / d;
1182
+ u = (p - noLensFrustum[0]) / (noLensFrustum[2] - noLensFrustum[0]);
1183
+ v = (q - noLensFrustum[3]) / (noLensFrustum[1] - noLensFrustum[3]);
1184
+ u = (viewport.x + u * viewport.width - 0.5) * 2.0;
1185
+ v = (viewport.y + v * viewport.height - 0.5) * 2.0;
1186
+ vertices[vidx * 5 + 0] = u;
1187
+ vertices[vidx * 5 + 1] = v;
1188
+ vertices[vidx * 5 + 2] = s;
1189
+ vertices[vidx * 5 + 3] = t;
1190
+ vertices[vidx * 5 + 4] = e;
1191
+ }
1192
+ }
1193
+ var w = lensFrustum[2] - lensFrustum[0];
1194
+ lensFrustum[0] = -(w + lensFrustum[0]);
1195
+ lensFrustum[2] = w - lensFrustum[2];
1196
+ w = noLensFrustum[2] - noLensFrustum[0];
1197
+ noLensFrustum[0] = -(w + noLensFrustum[0]);
1198
+ noLensFrustum[2] = w - noLensFrustum[2];
1199
+ viewport.x = 1 - (viewport.x + viewport.width);
1200
+ }
1201
+ return vertices;
1202
+ };
1203
+ CardboardDistorter.prototype.computeMeshIndices_ = function (width, height) {
1204
+ var indices = new Uint16Array(2 * (width - 1) * (height - 1) * 6);
1205
+ var halfwidth = width / 2;
1206
+ var halfheight = height / 2;
1207
+ var vidx = 0;
1208
+ var iidx = 0;
1209
+ for (var e = 0; e < 2; e++) {
1210
+ for (var j = 0; j < height; j++) {
1211
+ for (var i = 0; i < width; i++, vidx++) {
1212
+ if (i == 0 || j == 0) continue;
1213
+ if (i <= halfwidth == j <= halfheight) {
1214
+ indices[iidx++] = vidx;
1215
+ indices[iidx++] = vidx - width - 1;
1216
+ indices[iidx++] = vidx - width;
1217
+ indices[iidx++] = vidx - width - 1;
1218
+ indices[iidx++] = vidx;
1219
+ indices[iidx++] = vidx - 1;
1220
+ } else {
1221
+ indices[iidx++] = vidx - 1;
1222
+ indices[iidx++] = vidx - width;
1223
+ indices[iidx++] = vidx;
1224
+ indices[iidx++] = vidx - width;
1225
+ indices[iidx++] = vidx - 1;
1226
+ indices[iidx++] = vidx - width - 1;
1227
+ }
1228
+ }
1229
+ }
1230
+ }
1231
+ return indices;
1232
+ };
1233
+ CardboardDistorter.prototype.getOwnPropertyDescriptor_ = function (proto, attrName) {
1234
+ var descriptor = Object.getOwnPropertyDescriptor(proto, attrName);
1235
+ if (descriptor.get === undefined || descriptor.set === undefined) {
1236
+ descriptor.configurable = true;
1237
+ descriptor.enumerable = true;
1238
+ descriptor.get = function () {
1239
+ return this.getAttribute(attrName);
1240
+ };
1241
+ descriptor.set = function (val) {
1242
+ this.setAttribute(attrName, val);
1243
+ };
1244
+ }
1245
+ return descriptor;
1246
+ };
1247
+ var uiVS = ['attribute vec2 position;', 'uniform mat4 projectionMat;', 'void main() {', ' gl_Position = projectionMat * vec4( position, -1.0, 1.0 );', '}'].join('\n');
1248
+ var uiFS = ['precision mediump float;', 'uniform vec4 color;', 'void main() {', ' gl_FragColor = color;', '}'].join('\n');
1249
+ var DEG2RAD = Math.PI / 180.0;
1250
+ var kAnglePerGearSection = 60;
1251
+ var kOuterRimEndAngle = 12;
1252
+ var kInnerRimBeginAngle = 20;
1253
+ var kOuterRadius = 1;
1254
+ var kMiddleRadius = 0.75;
1255
+ var kInnerRadius = 0.3125;
1256
+ var kCenterLineThicknessDp = 4;
1257
+ var kButtonWidthDp = 28;
1258
+ var kTouchSlopFactor = 1.5;
1259
+ function CardboardUI(gl) {
1260
+ this.gl = gl;
1261
+ this.attribs = {
1262
+ position: 0
1263
+ };
1264
+ this.program = linkProgram(gl, uiVS, uiFS, this.attribs);
1265
+ this.uniforms = getProgramUniforms(gl, this.program);
1266
+ this.vertexBuffer = gl.createBuffer();
1267
+ this.gearOffset = 0;
1268
+ this.gearVertexCount = 0;
1269
+ this.arrowOffset = 0;
1270
+ this.arrowVertexCount = 0;
1271
+ this.projMat = new Float32Array(16);
1272
+ this.listener = null;
1273
+ this.onResize();
1274
+ }
1275
+ CardboardUI.prototype.destroy = function () {
1276
+ var gl = this.gl;
1277
+ if (this.listener) {
1278
+ gl.canvas.removeEventListener('click', this.listener, false);
1279
+ }
1280
+ gl.deleteProgram(this.program);
1281
+ gl.deleteBuffer(this.vertexBuffer);
1282
+ };
1283
+ CardboardUI.prototype.listen = function (optionsCallback, backCallback) {
1284
+ var canvas = this.gl.canvas;
1285
+ this.listener = function (event) {
1286
+ var midline = canvas.clientWidth / 2;
1287
+ var buttonSize = kButtonWidthDp * kTouchSlopFactor;
1288
+ if (event.clientX > midline - buttonSize && event.clientX < midline + buttonSize && event.clientY > canvas.clientHeight - buttonSize) {
1289
+ optionsCallback(event);
1290
+ }
1291
+ else if (event.clientX < buttonSize && event.clientY < buttonSize) {
1292
+ backCallback(event);
1293
+ }
1294
+ };
1295
+ canvas.addEventListener('click', this.listener, false);
1296
+ };
1297
+ CardboardUI.prototype.onResize = function () {
1298
+ var gl = this.gl;
1299
+ var self = this;
1300
+ var glState = [gl.ARRAY_BUFFER_BINDING];
1301
+ glPreserveState(gl, glState, function (gl) {
1302
+ var vertices = [];
1303
+ var midline = gl.drawingBufferWidth / 2;
1304
+ var physicalPixels = Math.max(screen.width, screen.height) * window.devicePixelRatio;
1305
+ var scalingRatio = gl.drawingBufferWidth / physicalPixels;
1306
+ var dps = scalingRatio * window.devicePixelRatio;
1307
+ var lineWidth = kCenterLineThicknessDp * dps / 2;
1308
+ var buttonSize = kButtonWidthDp * kTouchSlopFactor * dps;
1309
+ var buttonScale = kButtonWidthDp * dps / 2;
1310
+ var buttonBorder = (kButtonWidthDp * kTouchSlopFactor - kButtonWidthDp) * dps;
1311
+ vertices.push(midline - lineWidth, buttonSize);
1312
+ vertices.push(midline - lineWidth, gl.drawingBufferHeight);
1313
+ vertices.push(midline + lineWidth, buttonSize);
1314
+ vertices.push(midline + lineWidth, gl.drawingBufferHeight);
1315
+ self.gearOffset = vertices.length / 2;
1316
+ function addGearSegment(theta, r) {
1317
+ var angle = (90 - theta) * DEG2RAD;
1318
+ var x = Math.cos(angle);
1319
+ var y = Math.sin(angle);
1320
+ vertices.push(kInnerRadius * x * buttonScale + midline, kInnerRadius * y * buttonScale + buttonScale);
1321
+ vertices.push(r * x * buttonScale + midline, r * y * buttonScale + buttonScale);
1322
+ }
1323
+ for (var i = 0; i <= 6; i++) {
1324
+ var segmentTheta = i * kAnglePerGearSection;
1325
+ addGearSegment(segmentTheta, kOuterRadius);
1326
+ addGearSegment(segmentTheta + kOuterRimEndAngle, kOuterRadius);
1327
+ addGearSegment(segmentTheta + kInnerRimBeginAngle, kMiddleRadius);
1328
+ addGearSegment(segmentTheta + (kAnglePerGearSection - kInnerRimBeginAngle), kMiddleRadius);
1329
+ addGearSegment(segmentTheta + (kAnglePerGearSection - kOuterRimEndAngle), kOuterRadius);
1330
+ }
1331
+ self.gearVertexCount = vertices.length / 2 - self.gearOffset;
1332
+ self.arrowOffset = vertices.length / 2;
1333
+ function addArrowVertex(x, y) {
1334
+ vertices.push(buttonBorder + x, gl.drawingBufferHeight - buttonBorder - y);
1335
+ }
1336
+ var angledLineWidth = lineWidth / Math.sin(45 * DEG2RAD);
1337
+ addArrowVertex(0, buttonScale);
1338
+ addArrowVertex(buttonScale, 0);
1339
+ addArrowVertex(buttonScale + angledLineWidth, angledLineWidth);
1340
+ addArrowVertex(angledLineWidth, buttonScale + angledLineWidth);
1341
+ addArrowVertex(angledLineWidth, buttonScale - angledLineWidth);
1342
+ addArrowVertex(0, buttonScale);
1343
+ addArrowVertex(buttonScale, buttonScale * 2);
1344
+ addArrowVertex(buttonScale + angledLineWidth, buttonScale * 2 - angledLineWidth);
1345
+ addArrowVertex(angledLineWidth, buttonScale - angledLineWidth);
1346
+ addArrowVertex(0, buttonScale);
1347
+ addArrowVertex(angledLineWidth, buttonScale - lineWidth);
1348
+ addArrowVertex(kButtonWidthDp * dps, buttonScale - lineWidth);
1349
+ addArrowVertex(angledLineWidth, buttonScale + lineWidth);
1350
+ addArrowVertex(kButtonWidthDp * dps, buttonScale + lineWidth);
1351
+ self.arrowVertexCount = vertices.length / 2 - self.arrowOffset;
1352
+ gl.bindBuffer(gl.ARRAY_BUFFER, self.vertexBuffer);
1353
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
1354
+ });
1355
+ };
1356
+ CardboardUI.prototype.render = function () {
1357
+ var gl = this.gl;
1358
+ var self = this;
1359
+ var glState = [gl.CULL_FACE, gl.DEPTH_TEST, gl.BLEND, gl.SCISSOR_TEST, gl.STENCIL_TEST, gl.COLOR_WRITEMASK, gl.VIEWPORT, gl.CURRENT_PROGRAM, gl.ARRAY_BUFFER_BINDING];
1360
+ glPreserveState(gl, glState, function (gl) {
1361
+ gl.disable(gl.CULL_FACE);
1362
+ gl.disable(gl.DEPTH_TEST);
1363
+ gl.disable(gl.BLEND);
1364
+ gl.disable(gl.SCISSOR_TEST);
1365
+ gl.disable(gl.STENCIL_TEST);
1366
+ gl.colorMask(true, true, true, true);
1367
+ gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
1368
+ self.renderNoState();
1369
+ });
1370
+ };
1371
+ CardboardUI.prototype.renderNoState = function () {
1372
+ var gl = this.gl;
1373
+ gl.useProgram(this.program);
1374
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
1375
+ gl.enableVertexAttribArray(this.attribs.position);
1376
+ gl.vertexAttribPointer(this.attribs.position, 2, gl.FLOAT, false, 8, 0);
1377
+ gl.uniform4f(this.uniforms.color, 1.0, 1.0, 1.0, 1.0);
1378
+ orthoMatrix(this.projMat, 0, gl.drawingBufferWidth, 0, gl.drawingBufferHeight, 0.1, 1024.0);
1379
+ gl.uniformMatrix4fv(this.uniforms.projectionMat, false, this.projMat);
1380
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
1381
+ gl.drawArrays(gl.TRIANGLE_STRIP, this.gearOffset, this.gearVertexCount);
1382
+ gl.drawArrays(gl.TRIANGLE_STRIP, this.arrowOffset, this.arrowVertexCount);
1383
+ };
1384
+ function Distortion(coefficients) {
1385
+ this.coefficients = coefficients;
1386
+ }
1387
+ Distortion.prototype.distortInverse = function (radius) {
1388
+ var r0 = 0;
1389
+ var r1 = 1;
1390
+ var dr0 = radius - this.distort(r0);
1391
+ while (Math.abs(r1 - r0) > 0.0001 ) {
1392
+ var dr1 = radius - this.distort(r1);
1393
+ var r2 = r1 - dr1 * ((r1 - r0) / (dr1 - dr0));
1394
+ r0 = r1;
1395
+ r1 = r2;
1396
+ dr0 = dr1;
1397
+ }
1398
+ return r1;
1399
+ };
1400
+ Distortion.prototype.distort = function (radius) {
1401
+ var r2 = radius * radius;
1402
+ var ret = 0;
1403
+ for (var i = 0; i < this.coefficients.length; i++) {
1404
+ ret = r2 * (ret + this.coefficients[i]);
1405
+ }
1406
+ return (ret + 1) * radius;
1407
+ };
1408
+ var degToRad = Math.PI / 180;
1409
+ var radToDeg = 180 / Math.PI;
1410
+ var Vector3 = function Vector3(x, y, z) {
1411
+ this.x = x || 0;
1412
+ this.y = y || 0;
1413
+ this.z = z || 0;
1414
+ };
1415
+ Vector3.prototype = {
1416
+ constructor: Vector3,
1417
+ set: function set(x, y, z) {
1418
+ this.x = x;
1419
+ this.y = y;
1420
+ this.z = z;
1421
+ return this;
1422
+ },
1423
+ copy: function copy(v) {
1424
+ this.x = v.x;
1425
+ this.y = v.y;
1426
+ this.z = v.z;
1427
+ return this;
1428
+ },
1429
+ length: function length() {
1430
+ return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
1431
+ },
1432
+ normalize: function normalize() {
1433
+ var scalar = this.length();
1434
+ if (scalar !== 0) {
1435
+ var invScalar = 1 / scalar;
1436
+ this.multiplyScalar(invScalar);
1437
+ } else {
1438
+ this.x = 0;
1439
+ this.y = 0;
1440
+ this.z = 0;
1441
+ }
1442
+ return this;
1443
+ },
1444
+ multiplyScalar: function multiplyScalar(scalar) {
1445
+ this.x *= scalar;
1446
+ this.y *= scalar;
1447
+ this.z *= scalar;
1448
+ },
1449
+ applyQuaternion: function applyQuaternion(q) {
1450
+ var x = this.x;
1451
+ var y = this.y;
1452
+ var z = this.z;
1453
+ var qx = q.x;
1454
+ var qy = q.y;
1455
+ var qz = q.z;
1456
+ var qw = q.w;
1457
+ var ix = qw * x + qy * z - qz * y;
1458
+ var iy = qw * y + qz * x - qx * z;
1459
+ var iz = qw * z + qx * y - qy * x;
1460
+ var iw = -qx * x - qy * y - qz * z;
1461
+ this.x = ix * qw + iw * -qx + iy * -qz - iz * -qy;
1462
+ this.y = iy * qw + iw * -qy + iz * -qx - ix * -qz;
1463
+ this.z = iz * qw + iw * -qz + ix * -qy - iy * -qx;
1464
+ return this;
1465
+ },
1466
+ dot: function dot(v) {
1467
+ return this.x * v.x + this.y * v.y + this.z * v.z;
1468
+ },
1469
+ crossVectors: function crossVectors(a, b) {
1470
+ var ax = a.x,
1471
+ ay = a.y,
1472
+ az = a.z;
1473
+ var bx = b.x,
1474
+ by = b.y,
1475
+ bz = b.z;
1476
+ this.x = ay * bz - az * by;
1477
+ this.y = az * bx - ax * bz;
1478
+ this.z = ax * by - ay * bx;
1479
+ return this;
1480
+ }
1481
+ };
1482
+ var Quaternion = function Quaternion(x, y, z, w) {
1483
+ this.x = x || 0;
1484
+ this.y = y || 0;
1485
+ this.z = z || 0;
1486
+ this.w = w !== undefined ? w : 1;
1487
+ };
1488
+ Quaternion.prototype = {
1489
+ constructor: Quaternion,
1490
+ set: function set(x, y, z, w) {
1491
+ this.x = x;
1492
+ this.y = y;
1493
+ this.z = z;
1494
+ this.w = w;
1495
+ return this;
1496
+ },
1497
+ copy: function copy(quaternion) {
1498
+ this.x = quaternion.x;
1499
+ this.y = quaternion.y;
1500
+ this.z = quaternion.z;
1501
+ this.w = quaternion.w;
1502
+ return this;
1503
+ },
1504
+ setFromEulerXYZ: function setFromEulerXYZ(x, y, z) {
1505
+ var c1 = Math.cos(x / 2);
1506
+ var c2 = Math.cos(y / 2);
1507
+ var c3 = Math.cos(z / 2);
1508
+ var s1 = Math.sin(x / 2);
1509
+ var s2 = Math.sin(y / 2);
1510
+ var s3 = Math.sin(z / 2);
1511
+ this.x = s1 * c2 * c3 + c1 * s2 * s3;
1512
+ this.y = c1 * s2 * c3 - s1 * c2 * s3;
1513
+ this.z = c1 * c2 * s3 + s1 * s2 * c3;
1514
+ this.w = c1 * c2 * c3 - s1 * s2 * s3;
1515
+ return this;
1516
+ },
1517
+ setFromEulerYXZ: function setFromEulerYXZ(x, y, z) {
1518
+ var c1 = Math.cos(x / 2);
1519
+ var c2 = Math.cos(y / 2);
1520
+ var c3 = Math.cos(z / 2);
1521
+ var s1 = Math.sin(x / 2);
1522
+ var s2 = Math.sin(y / 2);
1523
+ var s3 = Math.sin(z / 2);
1524
+ this.x = s1 * c2 * c3 + c1 * s2 * s3;
1525
+ this.y = c1 * s2 * c3 - s1 * c2 * s3;
1526
+ this.z = c1 * c2 * s3 - s1 * s2 * c3;
1527
+ this.w = c1 * c2 * c3 + s1 * s2 * s3;
1528
+ return this;
1529
+ },
1530
+ setFromAxisAngle: function setFromAxisAngle(axis, angle) {
1531
+ var halfAngle = angle / 2,
1532
+ s = Math.sin(halfAngle);
1533
+ this.x = axis.x * s;
1534
+ this.y = axis.y * s;
1535
+ this.z = axis.z * s;
1536
+ this.w = Math.cos(halfAngle);
1537
+ return this;
1538
+ },
1539
+ multiply: function multiply(q) {
1540
+ return this.multiplyQuaternions(this, q);
1541
+ },
1542
+ multiplyQuaternions: function multiplyQuaternions(a, b) {
1543
+ var qax = a.x,
1544
+ qay = a.y,
1545
+ qaz = a.z,
1546
+ qaw = a.w;
1547
+ var qbx = b.x,
1548
+ qby = b.y,
1549
+ qbz = b.z,
1550
+ qbw = b.w;
1551
+ this.x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
1552
+ this.y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
1553
+ this.z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
1554
+ this.w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
1555
+ return this;
1556
+ },
1557
+ inverse: function inverse() {
1558
+ this.x *= -1;
1559
+ this.y *= -1;
1560
+ this.z *= -1;
1561
+ this.normalize();
1562
+ return this;
1563
+ },
1564
+ normalize: function normalize() {
1565
+ var l = Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w);
1566
+ if (l === 0) {
1567
+ this.x = 0;
1568
+ this.y = 0;
1569
+ this.z = 0;
1570
+ this.w = 1;
1571
+ } else {
1572
+ l = 1 / l;
1573
+ this.x = this.x * l;
1574
+ this.y = this.y * l;
1575
+ this.z = this.z * l;
1576
+ this.w = this.w * l;
1577
+ }
1578
+ return this;
1579
+ },
1580
+ slerp: function slerp(qb, t) {
1581
+ if (t === 0) return this;
1582
+ if (t === 1) return this.copy(qb);
1583
+ var x = this.x,
1584
+ y = this.y,
1585
+ z = this.z,
1586
+ w = this.w;
1587
+ var cosHalfTheta = w * qb.w + x * qb.x + y * qb.y + z * qb.z;
1588
+ if (cosHalfTheta < 0) {
1589
+ this.w = -qb.w;
1590
+ this.x = -qb.x;
1591
+ this.y = -qb.y;
1592
+ this.z = -qb.z;
1593
+ cosHalfTheta = -cosHalfTheta;
1594
+ } else {
1595
+ this.copy(qb);
1596
+ }
1597
+ if (cosHalfTheta >= 1.0) {
1598
+ this.w = w;
1599
+ this.x = x;
1600
+ this.y = y;
1601
+ this.z = z;
1602
+ return this;
1603
+ }
1604
+ var halfTheta = Math.acos(cosHalfTheta);
1605
+ var sinHalfTheta = Math.sqrt(1.0 - cosHalfTheta * cosHalfTheta);
1606
+ if (Math.abs(sinHalfTheta) < 0.001) {
1607
+ this.w = 0.5 * (w + this.w);
1608
+ this.x = 0.5 * (x + this.x);
1609
+ this.y = 0.5 * (y + this.y);
1610
+ this.z = 0.5 * (z + this.z);
1611
+ return this;
1612
+ }
1613
+ var ratioA = Math.sin((1 - t) * halfTheta) / sinHalfTheta,
1614
+ ratioB = Math.sin(t * halfTheta) / sinHalfTheta;
1615
+ this.w = w * ratioA + this.w * ratioB;
1616
+ this.x = x * ratioA + this.x * ratioB;
1617
+ this.y = y * ratioA + this.y * ratioB;
1618
+ this.z = z * ratioA + this.z * ratioB;
1619
+ return this;
1620
+ },
1621
+ setFromUnitVectors: function () {
1622
+ var v1, r;
1623
+ var EPS = 0.000001;
1624
+ return function (vFrom, vTo) {
1625
+ if (v1 === undefined) v1 = new Vector3();
1626
+ r = vFrom.dot(vTo) + 1;
1627
+ if (r < EPS) {
1628
+ r = 0;
1629
+ if (Math.abs(vFrom.x) > Math.abs(vFrom.z)) {
1630
+ v1.set(-vFrom.y, vFrom.x, 0);
1631
+ } else {
1632
+ v1.set(0, -vFrom.z, vFrom.y);
1633
+ }
1634
+ } else {
1635
+ v1.crossVectors(vFrom, vTo);
1636
+ }
1637
+ this.x = v1.x;
1638
+ this.y = v1.y;
1639
+ this.z = v1.z;
1640
+ this.w = r;
1641
+ this.normalize();
1642
+ return this;
1643
+ };
1644
+ }()
1645
+ };
1646
+ function Device(params) {
1647
+ this.width = params.width || getScreenWidth();
1648
+ this.height = params.height || getScreenHeight();
1649
+ this.widthMeters = params.widthMeters;
1650
+ this.heightMeters = params.heightMeters;
1651
+ this.bevelMeters = params.bevelMeters;
1652
+ }
1653
+ var DEFAULT_ANDROID = new Device({
1654
+ widthMeters: 0.110,
1655
+ heightMeters: 0.062,
1656
+ bevelMeters: 0.004
1657
+ });
1658
+ var DEFAULT_IOS = new Device({
1659
+ widthMeters: 0.1038,
1660
+ heightMeters: 0.0584,
1661
+ bevelMeters: 0.004
1662
+ });
1663
+ var Viewers = {
1664
+ CardboardV1: new CardboardViewer({
1665
+ id: 'CardboardV1',
1666
+ label: 'Cardboard I/O 2014',
1667
+ fov: 40,
1668
+ interLensDistance: 0.060,
1669
+ baselineLensDistance: 0.035,
1670
+ screenLensDistance: 0.042,
1671
+ distortionCoefficients: [0.441, 0.156],
1672
+ inverseCoefficients: [-0.4410035, 0.42756155, -0.4804439, 0.5460139, -0.58821183, 0.5733938, -0.48303202, 0.33299083, -0.17573841, 0.0651772, -0.01488963, 0.001559834]
1673
+ }),
1674
+ CardboardV2: new CardboardViewer({
1675
+ id: 'CardboardV2',
1676
+ label: 'Cardboard I/O 2015',
1677
+ fov: 60,
1678
+ interLensDistance: 0.064,
1679
+ baselineLensDistance: 0.035,
1680
+ screenLensDistance: 0.039,
1681
+ distortionCoefficients: [0.34, 0.55],
1682
+ inverseCoefficients: [-0.33836704, -0.18162185, 0.862655, -1.2462051, 1.0560602, -0.58208317, 0.21609078, -0.05444823, 0.009177956, -9.904169E-4, 6.183535E-5, -1.6981803E-6]
1683
+ })
1684
+ };
1685
+ function DeviceInfo(deviceParams, additionalViewers) {
1686
+ this.viewer = Viewers.CardboardV2;
1687
+ this.updateDeviceParams(deviceParams);
1688
+ this.distortion = new Distortion(this.viewer.distortionCoefficients);
1689
+ for (var i = 0; i < additionalViewers.length; i++) {
1690
+ var viewer = additionalViewers[i];
1691
+ Viewers[viewer.id] = new CardboardViewer(viewer);
1692
+ }
1693
+ }
1694
+ DeviceInfo.prototype.updateDeviceParams = function (deviceParams) {
1695
+ this.device = this.determineDevice_(deviceParams) || this.device;
1696
+ };
1697
+ DeviceInfo.prototype.getDevice = function () {
1698
+ return this.device;
1699
+ };
1700
+ DeviceInfo.prototype.setViewer = function (viewer) {
1701
+ this.viewer = viewer;
1702
+ this.distortion = new Distortion(this.viewer.distortionCoefficients);
1703
+ };
1704
+ DeviceInfo.prototype.determineDevice_ = function (deviceParams) {
1705
+ if (!deviceParams) {
1706
+ if (isIOS()) {
1707
+ console.warn('Using fallback iOS device measurements.');
1708
+ return DEFAULT_IOS;
1709
+ } else {
1710
+ console.warn('Using fallback Android device measurements.');
1711
+ return DEFAULT_ANDROID;
1712
+ }
1713
+ }
1714
+ var METERS_PER_INCH = 0.0254;
1715
+ var metersPerPixelX = METERS_PER_INCH / deviceParams.xdpi;
1716
+ var metersPerPixelY = METERS_PER_INCH / deviceParams.ydpi;
1717
+ var width = getScreenWidth();
1718
+ var height = getScreenHeight();
1719
+ return new Device({
1720
+ widthMeters: metersPerPixelX * width,
1721
+ heightMeters: metersPerPixelY * height,
1722
+ bevelMeters: deviceParams.bevelMm * 0.001
1723
+ });
1724
+ };
1725
+ DeviceInfo.prototype.getDistortedFieldOfViewLeftEye = function () {
1726
+ var viewer = this.viewer;
1727
+ var device = this.device;
1728
+ var distortion = this.distortion;
1729
+ var eyeToScreenDistance = viewer.screenLensDistance;
1730
+ var outerDist = (device.widthMeters - viewer.interLensDistance) / 2;
1731
+ var innerDist = viewer.interLensDistance / 2;
1732
+ var bottomDist = viewer.baselineLensDistance - device.bevelMeters;
1733
+ var topDist = device.heightMeters - bottomDist;
1734
+ var outerAngle = radToDeg * Math.atan(distortion.distort(outerDist / eyeToScreenDistance));
1735
+ var innerAngle = radToDeg * Math.atan(distortion.distort(innerDist / eyeToScreenDistance));
1736
+ var bottomAngle = radToDeg * Math.atan(distortion.distort(bottomDist / eyeToScreenDistance));
1737
+ var topAngle = radToDeg * Math.atan(distortion.distort(topDist / eyeToScreenDistance));
1738
+ return {
1739
+ leftDegrees: Math.min(outerAngle, viewer.fov),
1740
+ rightDegrees: Math.min(innerAngle, viewer.fov),
1741
+ downDegrees: Math.min(bottomAngle, viewer.fov),
1742
+ upDegrees: Math.min(topAngle, viewer.fov)
1743
+ };
1744
+ };
1745
+ DeviceInfo.prototype.getLeftEyeVisibleTanAngles = function () {
1746
+ var viewer = this.viewer;
1747
+ var device = this.device;
1748
+ var distortion = this.distortion;
1749
+ var fovLeft = Math.tan(-degToRad * viewer.fov);
1750
+ var fovTop = Math.tan(degToRad * viewer.fov);
1751
+ var fovRight = Math.tan(degToRad * viewer.fov);
1752
+ var fovBottom = Math.tan(-degToRad * viewer.fov);
1753
+ var halfWidth = device.widthMeters / 4;
1754
+ var halfHeight = device.heightMeters / 2;
1755
+ var verticalLensOffset = viewer.baselineLensDistance - device.bevelMeters - halfHeight;
1756
+ var centerX = viewer.interLensDistance / 2 - halfWidth;
1757
+ var centerY = -verticalLensOffset;
1758
+ var centerZ = viewer.screenLensDistance;
1759
+ var screenLeft = distortion.distort((centerX - halfWidth) / centerZ);
1760
+ var screenTop = distortion.distort((centerY + halfHeight) / centerZ);
1761
+ var screenRight = distortion.distort((centerX + halfWidth) / centerZ);
1762
+ var screenBottom = distortion.distort((centerY - halfHeight) / centerZ);
1763
+ var result = new Float32Array(4);
1764
+ result[0] = Math.max(fovLeft, screenLeft);
1765
+ result[1] = Math.min(fovTop, screenTop);
1766
+ result[2] = Math.min(fovRight, screenRight);
1767
+ result[3] = Math.max(fovBottom, screenBottom);
1768
+ return result;
1769
+ };
1770
+ DeviceInfo.prototype.getLeftEyeNoLensTanAngles = function () {
1771
+ var viewer = this.viewer;
1772
+ var device = this.device;
1773
+ var distortion = this.distortion;
1774
+ var result = new Float32Array(4);
1775
+ var fovLeft = distortion.distortInverse(Math.tan(-degToRad * viewer.fov));
1776
+ var fovTop = distortion.distortInverse(Math.tan(degToRad * viewer.fov));
1777
+ var fovRight = distortion.distortInverse(Math.tan(degToRad * viewer.fov));
1778
+ var fovBottom = distortion.distortInverse(Math.tan(-degToRad * viewer.fov));
1779
+ var halfWidth = device.widthMeters / 4;
1780
+ var halfHeight = device.heightMeters / 2;
1781
+ var verticalLensOffset = viewer.baselineLensDistance - device.bevelMeters - halfHeight;
1782
+ var centerX = viewer.interLensDistance / 2 - halfWidth;
1783
+ var centerY = -verticalLensOffset;
1784
+ var centerZ = viewer.screenLensDistance;
1785
+ var screenLeft = (centerX - halfWidth) / centerZ;
1786
+ var screenTop = (centerY + halfHeight) / centerZ;
1787
+ var screenRight = (centerX + halfWidth) / centerZ;
1788
+ var screenBottom = (centerY - halfHeight) / centerZ;
1789
+ result[0] = Math.max(fovLeft, screenLeft);
1790
+ result[1] = Math.min(fovTop, screenTop);
1791
+ result[2] = Math.min(fovRight, screenRight);
1792
+ result[3] = Math.max(fovBottom, screenBottom);
1793
+ return result;
1794
+ };
1795
+ DeviceInfo.prototype.getLeftEyeVisibleScreenRect = function (undistortedFrustum) {
1796
+ var viewer = this.viewer;
1797
+ var device = this.device;
1798
+ var dist = viewer.screenLensDistance;
1799
+ var eyeX = (device.widthMeters - viewer.interLensDistance) / 2;
1800
+ var eyeY = viewer.baselineLensDistance - device.bevelMeters;
1801
+ var left = (undistortedFrustum[0] * dist + eyeX) / device.widthMeters;
1802
+ var top = (undistortedFrustum[1] * dist + eyeY) / device.heightMeters;
1803
+ var right = (undistortedFrustum[2] * dist + eyeX) / device.widthMeters;
1804
+ var bottom = (undistortedFrustum[3] * dist + eyeY) / device.heightMeters;
1805
+ return {
1806
+ x: left,
1807
+ y: bottom,
1808
+ width: right - left,
1809
+ height: top - bottom
1810
+ };
1811
+ };
1812
+ DeviceInfo.prototype.getFieldOfViewLeftEye = function (opt_isUndistorted) {
1813
+ return opt_isUndistorted ? this.getUndistortedFieldOfViewLeftEye() : this.getDistortedFieldOfViewLeftEye();
1814
+ };
1815
+ DeviceInfo.prototype.getFieldOfViewRightEye = function (opt_isUndistorted) {
1816
+ var fov = this.getFieldOfViewLeftEye(opt_isUndistorted);
1817
+ return {
1818
+ leftDegrees: fov.rightDegrees,
1819
+ rightDegrees: fov.leftDegrees,
1820
+ upDegrees: fov.upDegrees,
1821
+ downDegrees: fov.downDegrees
1822
+ };
1823
+ };
1824
+ DeviceInfo.prototype.getUndistortedFieldOfViewLeftEye = function () {
1825
+ var p = this.getUndistortedParams_();
1826
+ return {
1827
+ leftDegrees: radToDeg * Math.atan(p.outerDist),
1828
+ rightDegrees: radToDeg * Math.atan(p.innerDist),
1829
+ downDegrees: radToDeg * Math.atan(p.bottomDist),
1830
+ upDegrees: radToDeg * Math.atan(p.topDist)
1831
+ };
1832
+ };
1833
+ DeviceInfo.prototype.getUndistortedViewportLeftEye = function () {
1834
+ var p = this.getUndistortedParams_();
1835
+ var viewer = this.viewer;
1836
+ var device = this.device;
1837
+ var eyeToScreenDistance = viewer.screenLensDistance;
1838
+ var screenWidth = device.widthMeters / eyeToScreenDistance;
1839
+ var screenHeight = device.heightMeters / eyeToScreenDistance;
1840
+ var xPxPerTanAngle = device.width / screenWidth;
1841
+ var yPxPerTanAngle = device.height / screenHeight;
1842
+ var x = Math.round((p.eyePosX - p.outerDist) * xPxPerTanAngle);
1843
+ var y = Math.round((p.eyePosY - p.bottomDist) * yPxPerTanAngle);
1844
+ return {
1845
+ x: x,
1846
+ y: y,
1847
+ width: Math.round((p.eyePosX + p.innerDist) * xPxPerTanAngle) - x,
1848
+ height: Math.round((p.eyePosY + p.topDist) * yPxPerTanAngle) - y
1849
+ };
1850
+ };
1851
+ DeviceInfo.prototype.getUndistortedParams_ = function () {
1852
+ var viewer = this.viewer;
1853
+ var device = this.device;
1854
+ var distortion = this.distortion;
1855
+ var eyeToScreenDistance = viewer.screenLensDistance;
1856
+ var halfLensDistance = viewer.interLensDistance / 2 / eyeToScreenDistance;
1857
+ var screenWidth = device.widthMeters / eyeToScreenDistance;
1858
+ var screenHeight = device.heightMeters / eyeToScreenDistance;
1859
+ var eyePosX = screenWidth / 2 - halfLensDistance;
1860
+ var eyePosY = (viewer.baselineLensDistance - device.bevelMeters) / eyeToScreenDistance;
1861
+ var maxFov = viewer.fov;
1862
+ var viewerMax = distortion.distortInverse(Math.tan(degToRad * maxFov));
1863
+ var outerDist = Math.min(eyePosX, viewerMax);
1864
+ var innerDist = Math.min(halfLensDistance, viewerMax);
1865
+ var bottomDist = Math.min(eyePosY, viewerMax);
1866
+ var topDist = Math.min(screenHeight - eyePosY, viewerMax);
1867
+ return {
1868
+ outerDist: outerDist,
1869
+ innerDist: innerDist,
1870
+ topDist: topDist,
1871
+ bottomDist: bottomDist,
1872
+ eyePosX: eyePosX,
1873
+ eyePosY: eyePosY
1874
+ };
1875
+ };
1876
+ function CardboardViewer(params) {
1877
+ this.id = params.id;
1878
+ this.label = params.label;
1879
+ this.fov = params.fov;
1880
+ this.interLensDistance = params.interLensDistance;
1881
+ this.baselineLensDistance = params.baselineLensDistance;
1882
+ this.screenLensDistance = params.screenLensDistance;
1883
+ this.distortionCoefficients = params.distortionCoefficients;
1884
+ this.inverseCoefficients = params.inverseCoefficients;
1885
+ }
1886
+ DeviceInfo.Viewers = Viewers;
1887
+ var format = 1;
1888
+ var last_updated = "2018-02-20T22:55:10Z";
1889
+ var devices = [{"type":"android","rules":[{"mdmh":"asus/*/Nexus 7/*"},{"ua":"Nexus 7"}],"dpi":[320.8,323],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"asus/*/ASUS_Z00AD/*"},{"ua":"ASUS_Z00AD"}],"dpi":[403,404.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Google/*/Pixel XL/*"},{"ua":"Pixel XL"}],"dpi":[537.9,533],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Google/*/Pixel/*"},{"ua":"Pixel"}],"dpi":[432.6,436.7],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"HTC/*/HTC6435LVW/*"},{"ua":"HTC6435LVW"}],"dpi":[449.7,443.3],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"HTC/*/HTC One XL/*"},{"ua":"HTC One XL"}],"dpi":[315.3,314.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"htc/*/Nexus 9/*"},{"ua":"Nexus 9"}],"dpi":289,"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"HTC/*/HTC One M9/*"},{"ua":"HTC One M9"}],"dpi":[442.5,443.3],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"HTC/*/HTC One_M8/*"},{"ua":"HTC One_M8"}],"dpi":[449.7,447.4],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"HTC/*/HTC One/*"},{"ua":"HTC One"}],"dpi":472.8,"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Huawei/*/Nexus 6P/*"},{"ua":"Nexus 6P"}],"dpi":[515.1,518],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"LENOVO/*/Lenovo PB2-690Y/*"},{"ua":"Lenovo PB2-690Y"}],"dpi":[457.2,454.713],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"LGE/*/Nexus 5X/*"},{"ua":"Nexus 5X"}],"dpi":[422,419.9],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"LGE/*/LGMS345/*"},{"ua":"LGMS345"}],"dpi":[221.7,219.1],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"LGE/*/LG-D800/*"},{"ua":"LG-D800"}],"dpi":[422,424.1],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"LGE/*/LG-D850/*"},{"ua":"LG-D850"}],"dpi":[537.9,541.9],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"LGE/*/VS985 4G/*"},{"ua":"VS985 4G"}],"dpi":[537.9,535.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"LGE/*/Nexus 5/*"},{"ua":"Nexus 5 B"}],"dpi":[442.4,444.8],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"LGE/*/Nexus 4/*"},{"ua":"Nexus 4"}],"dpi":[319.8,318.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"LGE/*/LG-P769/*"},{"ua":"LG-P769"}],"dpi":[240.6,247.5],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"LGE/*/LGMS323/*"},{"ua":"LGMS323"}],"dpi":[206.6,204.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"LGE/*/LGLS996/*"},{"ua":"LGLS996"}],"dpi":[403.4,401.5],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Micromax/*/4560MMX/*"},{"ua":"4560MMX"}],"dpi":[240,219.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Micromax/*/A250/*"},{"ua":"Micromax A250"}],"dpi":[480,446.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Micromax/*/Micromax AQ4501/*"},{"ua":"Micromax AQ4501"}],"dpi":240,"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"motorola/*/G5/*"},{"ua":"Moto G (5) Plus"}],"dpi":[403.4,403],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/DROID RAZR/*"},{"ua":"DROID RAZR"}],"dpi":[368.1,256.7],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/XT830C/*"},{"ua":"XT830C"}],"dpi":[254,255.9],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/XT1021/*"},{"ua":"XT1021"}],"dpi":[254,256.7],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"motorola/*/XT1023/*"},{"ua":"XT1023"}],"dpi":[254,256.7],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"motorola/*/XT1028/*"},{"ua":"XT1028"}],"dpi":[326.6,327.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/XT1034/*"},{"ua":"XT1034"}],"dpi":[326.6,328.4],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"motorola/*/XT1053/*"},{"ua":"XT1053"}],"dpi":[315.3,316.1],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/XT1562/*"},{"ua":"XT1562"}],"dpi":[403.4,402.7],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/Nexus 6/*"},{"ua":"Nexus 6 B"}],"dpi":[494.3,489.7],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/XT1063/*"},{"ua":"XT1063"}],"dpi":[295,296.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/XT1064/*"},{"ua":"XT1064"}],"dpi":[295,295.6],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"motorola/*/XT1092/*"},{"ua":"XT1092"}],"dpi":[422,424.1],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"motorola/*/XT1095/*"},{"ua":"XT1095"}],"dpi":[422,423.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/G4/*"},{"ua":"Moto G (4)"}],"dpi":401,"bw":4,"ac":1000},{"type":"android","rules":[{"mdmh":"OnePlus/*/A0001/*"},{"ua":"A0001"}],"dpi":[403.4,401],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"OnePlus/*/ONE E1005/*"},{"ua":"ONE E1005"}],"dpi":[442.4,441.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"OnePlus/*/ONE A2005/*"},{"ua":"ONE A2005"}],"dpi":[391.9,405.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"OnePlus/*/ONEPLUS A5000/*"},{"ua":"ONEPLUS A5000 "}],"dpi":[403.411,399.737],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"OnePlus/*/ONE A5010/*"},{"ua":"ONEPLUS A5010"}],"dpi":[403,400],"bw":2,"ac":1000},{"type":"android","rules":[{"mdmh":"OPPO/*/X909/*"},{"ua":"X909"}],"dpi":[442.4,444.1],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/GT-I9082/*"},{"ua":"GT-I9082"}],"dpi":[184.7,185.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G360P/*"},{"ua":"SM-G360P"}],"dpi":[196.7,205.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/Nexus S/*"},{"ua":"Nexus S"}],"dpi":[234.5,229.8],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/GT-I9300/*"},{"ua":"GT-I9300"}],"dpi":[304.8,303.9],"bw":5,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-T230NU/*"},{"ua":"SM-T230NU"}],"dpi":216,"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SGH-T399/*"},{"ua":"SGH-T399"}],"dpi":[217.7,231.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SGH-M919/*"},{"ua":"SGH-M919"}],"dpi":[440.8,437.7],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-N9005/*"},{"ua":"SM-N9005"}],"dpi":[386.4,387],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SAMSUNG-SM-N900A/*"},{"ua":"SAMSUNG-SM-N900A"}],"dpi":[386.4,387.7],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/GT-I9500/*"},{"ua":"GT-I9500"}],"dpi":[442.5,443.3],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/GT-I9505/*"},{"ua":"GT-I9505"}],"dpi":439.4,"bw":4,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G900F/*"},{"ua":"SM-G900F"}],"dpi":[415.6,431.6],"bw":5,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G900M/*"},{"ua":"SM-G900M"}],"dpi":[415.6,431.6],"bw":5,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G800F/*"},{"ua":"SM-G800F"}],"dpi":326.8,"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G906S/*"},{"ua":"SM-G906S"}],"dpi":[562.7,572.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/GT-I9300/*"},{"ua":"GT-I9300"}],"dpi":[306.7,304.8],"bw":5,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-T535/*"},{"ua":"SM-T535"}],"dpi":[142.6,136.4],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-N920C/*"},{"ua":"SM-N920C"}],"dpi":[515.1,518.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-N920P/*"},{"ua":"SM-N920P"}],"dpi":[386.3655,390.144],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-N920W8/*"},{"ua":"SM-N920W8"}],"dpi":[515.1,518.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/GT-I9300I/*"},{"ua":"GT-I9300I"}],"dpi":[304.8,305.8],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/GT-I9195/*"},{"ua":"GT-I9195"}],"dpi":[249.4,256.7],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SPH-L520/*"},{"ua":"SPH-L520"}],"dpi":[249.4,255.9],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SAMSUNG-SGH-I717/*"},{"ua":"SAMSUNG-SGH-I717"}],"dpi":285.8,"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SPH-D710/*"},{"ua":"SPH-D710"}],"dpi":[217.7,204.2],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/GT-N7100/*"},{"ua":"GT-N7100"}],"dpi":265.1,"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SCH-I605/*"},{"ua":"SCH-I605"}],"dpi":265.1,"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/Galaxy Nexus/*"},{"ua":"Galaxy Nexus"}],"dpi":[315.3,314.2],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-N910H/*"},{"ua":"SM-N910H"}],"dpi":[515.1,518],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-N910C/*"},{"ua":"SM-N910C"}],"dpi":[515.2,520.2],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G130M/*"},{"ua":"SM-G130M"}],"dpi":[165.9,164.8],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G928I/*"},{"ua":"SM-G928I"}],"dpi":[515.1,518.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G920F/*"},{"ua":"SM-G920F"}],"dpi":580.6,"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G920P/*"},{"ua":"SM-G920P"}],"dpi":[522.5,577],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G925F/*"},{"ua":"SM-G925F"}],"dpi":580.6,"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G925V/*"},{"ua":"SM-G925V"}],"dpi":[522.5,576.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G930F/*"},{"ua":"SM-G930F"}],"dpi":576.6,"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G935F/*"},{"ua":"SM-G935F"}],"dpi":533,"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G950F/*"},{"ua":"SM-G950F"}],"dpi":[562.707,565.293],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G955U/*"},{"ua":"SM-G955U"}],"dpi":[522.514,525.762],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"Sony/*/C6903/*"},{"ua":"C6903"}],"dpi":[442.5,443.3],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"Sony/*/D6653/*"},{"ua":"D6653"}],"dpi":[428.6,427.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Sony/*/E6653/*"},{"ua":"E6653"}],"dpi":[428.6,425.7],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Sony/*/E6853/*"},{"ua":"E6853"}],"dpi":[403.4,401.9],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Sony/*/SGP321/*"},{"ua":"SGP321"}],"dpi":[224.7,224.1],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"TCT/*/ALCATEL ONE TOUCH Fierce/*"},{"ua":"ALCATEL ONE TOUCH Fierce"}],"dpi":[240,247.5],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"THL/*/thl 5000/*"},{"ua":"thl 5000"}],"dpi":[480,443.3],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Fly/*/IQ4412/*"},{"ua":"IQ4412"}],"dpi":307.9,"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"ZTE/*/ZTE Blade L2/*"},{"ua":"ZTE Blade L2"}],"dpi":240,"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"BENEVE/*/VR518/*"},{"ua":"VR518"}],"dpi":480,"bw":3,"ac":500},{"type":"ios","rules":[{"res":[640,960]}],"dpi":[325.1,328.4],"bw":4,"ac":1000},{"type":"ios","rules":[{"res":[640,1136]}],"dpi":[317.1,320.2],"bw":3,"ac":1000},{"type":"ios","rules":[{"res":[750,1334]}],"dpi":326.4,"bw":4,"ac":1000},{"type":"ios","rules":[{"res":[1242,2208]}],"dpi":[453.6,458.4],"bw":4,"ac":1000},{"type":"ios","rules":[{"res":[1125,2001]}],"dpi":[410.9,415.4],"bw":4,"ac":1000},{"type":"ios","rules":[{"res":[1125,2436]}],"dpi":458,"bw":4,"ac":1000}];
1890
+ var DPDB_CACHE = {
1891
+ format: format,
1892
+ last_updated: last_updated,
1893
+ devices: devices
1894
+ };
1895
+ function Dpdb(url, onDeviceParamsUpdated) {
1896
+ this.dpdb = DPDB_CACHE;
1897
+ this.recalculateDeviceParams_();
1898
+ if (url) {
1899
+ this.onDeviceParamsUpdated = onDeviceParamsUpdated;
1900
+ var xhr = new XMLHttpRequest();
1901
+ var obj = this;
1902
+ xhr.open('GET', url, true);
1903
+ xhr.addEventListener('load', function () {
1904
+ obj.loading = false;
1905
+ if (xhr.status >= 200 && xhr.status <= 299) {
1906
+ obj.dpdb = JSON.parse(xhr.response);
1907
+ obj.recalculateDeviceParams_();
1908
+ } else {
1909
+ console.error('Error loading online DPDB!');
1910
+ }
1911
+ });
1912
+ xhr.send();
1913
+ }
1914
+ }
1915
+ Dpdb.prototype.getDeviceParams = function () {
1916
+ return this.deviceParams;
1917
+ };
1918
+ Dpdb.prototype.recalculateDeviceParams_ = function () {
1919
+ var newDeviceParams = this.calcDeviceParams_();
1920
+ if (newDeviceParams) {
1921
+ this.deviceParams = newDeviceParams;
1922
+ if (this.onDeviceParamsUpdated) {
1923
+ this.onDeviceParamsUpdated(this.deviceParams);
1924
+ }
1925
+ } else {
1926
+ console.error('Failed to recalculate device parameters.');
1927
+ }
1928
+ };
1929
+ Dpdb.prototype.calcDeviceParams_ = function () {
1930
+ var db = this.dpdb;
1931
+ if (!db) {
1932
+ console.error('DPDB not available.');
1933
+ return null;
1934
+ }
1935
+ if (db.format != 1) {
1936
+ console.error('DPDB has unexpected format version.');
1937
+ return null;
1938
+ }
1939
+ if (!db.devices || !db.devices.length) {
1940
+ console.error('DPDB does not have a devices section.');
1941
+ return null;
1942
+ }
1943
+ var userAgent = navigator.userAgent || navigator.vendor || window.opera;
1944
+ var width = getScreenWidth();
1945
+ var height = getScreenHeight();
1946
+ if (!db.devices) {
1947
+ console.error('DPDB has no devices section.');
1948
+ return null;
1949
+ }
1950
+ for (var i = 0; i < db.devices.length; i++) {
1951
+ var device = db.devices[i];
1952
+ if (!device.rules) {
1953
+ console.warn('Device[' + i + '] has no rules section.');
1954
+ continue;
1955
+ }
1956
+ if (device.type != 'ios' && device.type != 'android') {
1957
+ console.warn('Device[' + i + '] has invalid type.');
1958
+ continue;
1959
+ }
1960
+ if (isIOS() != (device.type == 'ios')) continue;
1961
+ var matched = false;
1962
+ for (var j = 0; j < device.rules.length; j++) {
1963
+ var rule = device.rules[j];
1964
+ if (this.matchRule_(rule, userAgent, width, height)) {
1965
+ matched = true;
1966
+ break;
1967
+ }
1968
+ }
1969
+ if (!matched) continue;
1970
+ var xdpi = device.dpi[0] || device.dpi;
1971
+ var ydpi = device.dpi[1] || device.dpi;
1972
+ return new DeviceParams({ xdpi: xdpi, ydpi: ydpi, bevelMm: device.bw });
1973
+ }
1974
+ console.warn('No DPDB device match.');
1975
+ return null;
1976
+ };
1977
+ Dpdb.prototype.matchRule_ = function (rule, ua, screenWidth, screenHeight) {
1978
+ if (!rule.ua && !rule.res) return false;
1979
+ if (rule.ua && ua.indexOf(rule.ua) < 0) return false;
1980
+ if (rule.res) {
1981
+ if (!rule.res[0] || !rule.res[1]) return false;
1982
+ var resX = rule.res[0];
1983
+ var resY = rule.res[1];
1984
+ if (Math.min(screenWidth, screenHeight) != Math.min(resX, resY) || Math.max(screenWidth, screenHeight) != Math.max(resX, resY)) {
1985
+ return false;
1986
+ }
1987
+ }
1988
+ return true;
1989
+ };
1990
+ function DeviceParams(params) {
1991
+ this.xdpi = params.xdpi;
1992
+ this.ydpi = params.ydpi;
1993
+ this.bevelMm = params.bevelMm;
1994
+ }
1995
+ function SensorSample(sample, timestampS) {
1996
+ this.set(sample, timestampS);
1997
+ }
1998
+ SensorSample.prototype.set = function (sample, timestampS) {
1999
+ this.sample = sample;
2000
+ this.timestampS = timestampS;
2001
+ };
2002
+ SensorSample.prototype.copy = function (sensorSample) {
2003
+ this.set(sensorSample.sample, sensorSample.timestampS);
2004
+ };
2005
+ function ComplementaryFilter(kFilter, isDebug) {
2006
+ this.kFilter = kFilter;
2007
+ this.isDebug = isDebug;
2008
+ this.currentAccelMeasurement = new SensorSample();
2009
+ this.currentGyroMeasurement = new SensorSample();
2010
+ this.previousGyroMeasurement = new SensorSample();
2011
+ if (isIOS()) {
2012
+ this.filterQ = new Quaternion(-1, 0, 0, 1);
2013
+ } else {
2014
+ this.filterQ = new Quaternion(1, 0, 0, 1);
2015
+ }
2016
+ this.previousFilterQ = new Quaternion();
2017
+ this.previousFilterQ.copy(this.filterQ);
2018
+ this.accelQ = new Quaternion();
2019
+ this.isOrientationInitialized = false;
2020
+ this.estimatedGravity = new Vector3();
2021
+ this.measuredGravity = new Vector3();
2022
+ this.gyroIntegralQ = new Quaternion();
2023
+ }
2024
+ ComplementaryFilter.prototype.addAccelMeasurement = function (vector, timestampS) {
2025
+ this.currentAccelMeasurement.set(vector, timestampS);
2026
+ };
2027
+ ComplementaryFilter.prototype.addGyroMeasurement = function (vector, timestampS) {
2028
+ this.currentGyroMeasurement.set(vector, timestampS);
2029
+ var deltaT = timestampS - this.previousGyroMeasurement.timestampS;
2030
+ if (isTimestampDeltaValid(deltaT)) {
2031
+ this.run_();
2032
+ }
2033
+ this.previousGyroMeasurement.copy(this.currentGyroMeasurement);
2034
+ };
2035
+ ComplementaryFilter.prototype.run_ = function () {
2036
+ if (!this.isOrientationInitialized) {
2037
+ this.accelQ = this.accelToQuaternion_(this.currentAccelMeasurement.sample);
2038
+ this.previousFilterQ.copy(this.accelQ);
2039
+ this.isOrientationInitialized = true;
2040
+ return;
2041
+ }
2042
+ var deltaT = this.currentGyroMeasurement.timestampS - this.previousGyroMeasurement.timestampS;
2043
+ var gyroDeltaQ = this.gyroToQuaternionDelta_(this.currentGyroMeasurement.sample, deltaT);
2044
+ this.gyroIntegralQ.multiply(gyroDeltaQ);
2045
+ this.filterQ.copy(this.previousFilterQ);
2046
+ this.filterQ.multiply(gyroDeltaQ);
2047
+ var invFilterQ = new Quaternion();
2048
+ invFilterQ.copy(this.filterQ);
2049
+ invFilterQ.inverse();
2050
+ this.estimatedGravity.set(0, 0, -1);
2051
+ this.estimatedGravity.applyQuaternion(invFilterQ);
2052
+ this.estimatedGravity.normalize();
2053
+ this.measuredGravity.copy(this.currentAccelMeasurement.sample);
2054
+ this.measuredGravity.normalize();
2055
+ var deltaQ = new Quaternion();
2056
+ deltaQ.setFromUnitVectors(this.estimatedGravity, this.measuredGravity);
2057
+ deltaQ.inverse();
2058
+ if (this.isDebug) {
2059
+ console.log('Delta: %d deg, G_est: (%s, %s, %s), G_meas: (%s, %s, %s)', radToDeg * getQuaternionAngle(deltaQ), this.estimatedGravity.x.toFixed(1), this.estimatedGravity.y.toFixed(1), this.estimatedGravity.z.toFixed(1), this.measuredGravity.x.toFixed(1), this.measuredGravity.y.toFixed(1), this.measuredGravity.z.toFixed(1));
2060
+ }
2061
+ var targetQ = new Quaternion();
2062
+ targetQ.copy(this.filterQ);
2063
+ targetQ.multiply(deltaQ);
2064
+ this.filterQ.slerp(targetQ, 1 - this.kFilter);
2065
+ this.previousFilterQ.copy(this.filterQ);
2066
+ };
2067
+ ComplementaryFilter.prototype.getOrientation = function () {
2068
+ return this.filterQ;
2069
+ };
2070
+ ComplementaryFilter.prototype.accelToQuaternion_ = function (accel) {
2071
+ var normAccel = new Vector3();
2072
+ normAccel.copy(accel);
2073
+ normAccel.normalize();
2074
+ var quat = new Quaternion();
2075
+ quat.setFromUnitVectors(new Vector3(0, 0, -1), normAccel);
2076
+ quat.inverse();
2077
+ return quat;
2078
+ };
2079
+ ComplementaryFilter.prototype.gyroToQuaternionDelta_ = function (gyro, dt) {
2080
+ var quat = new Quaternion();
2081
+ var axis = new Vector3();
2082
+ axis.copy(gyro);
2083
+ axis.normalize();
2084
+ quat.setFromAxisAngle(axis, gyro.length() * dt);
2085
+ return quat;
2086
+ };
2087
+ function PosePredictor(predictionTimeS, isDebug) {
2088
+ this.predictionTimeS = predictionTimeS;
2089
+ this.isDebug = isDebug;
2090
+ this.previousQ = new Quaternion();
2091
+ this.previousTimestampS = null;
2092
+ this.deltaQ = new Quaternion();
2093
+ this.outQ = new Quaternion();
2094
+ }
2095
+ PosePredictor.prototype.getPrediction = function (currentQ, gyro, timestampS) {
2096
+ if (!this.previousTimestampS) {
2097
+ this.previousQ.copy(currentQ);
2098
+ this.previousTimestampS = timestampS;
2099
+ return currentQ;
2100
+ }
2101
+ var axis = new Vector3();
2102
+ axis.copy(gyro);
2103
+ axis.normalize();
2104
+ var angularSpeed = gyro.length();
2105
+ if (angularSpeed < degToRad * 20) {
2106
+ if (this.isDebug) {
2107
+ console.log('Moving slowly, at %s deg/s: no prediction', (radToDeg * angularSpeed).toFixed(1));
2108
+ }
2109
+ this.outQ.copy(currentQ);
2110
+ this.previousQ.copy(currentQ);
2111
+ return this.outQ;
2112
+ }
2113
+ var predictAngle = angularSpeed * this.predictionTimeS;
2114
+ this.deltaQ.setFromAxisAngle(axis, predictAngle);
2115
+ this.outQ.copy(this.previousQ);
2116
+ this.outQ.multiply(this.deltaQ);
2117
+ this.previousQ.copy(currentQ);
2118
+ this.previousTimestampS = timestampS;
2119
+ return this.outQ;
2120
+ };
2121
+ function FusionPoseSensor(kFilter, predictionTime, yawOnly, isDebug) {
2122
+ this.yawOnly = yawOnly;
2123
+ this.accelerometer = new Vector3();
2124
+ this.gyroscope = new Vector3();
2125
+ this.filter = new ComplementaryFilter(kFilter, isDebug);
2126
+ this.posePredictor = new PosePredictor(predictionTime, isDebug);
2127
+ this.isFirefoxAndroid = isFirefoxAndroid();
2128
+ this.isIOS = isIOS();
2129
+ var chromeVersion = getChromeVersion();
2130
+ this.isDeviceMotionInRadians = !this.isIOS && chromeVersion && chromeVersion < 66;
2131
+ this.isWithoutDeviceMotion = isChromeWithoutDeviceMotion();
2132
+ this.filterToWorldQ = new Quaternion();
2133
+ if (isIOS()) {
2134
+ this.filterToWorldQ.setFromAxisAngle(new Vector3(1, 0, 0), Math.PI / 2);
2135
+ } else {
2136
+ this.filterToWorldQ.setFromAxisAngle(new Vector3(1, 0, 0), -Math.PI / 2);
2137
+ }
2138
+ this.inverseWorldToScreenQ = new Quaternion();
2139
+ this.worldToScreenQ = new Quaternion();
2140
+ this.originalPoseAdjustQ = new Quaternion();
2141
+ this.originalPoseAdjustQ.setFromAxisAngle(new Vector3(0, 0, 1), -window.orientation * Math.PI / 180);
2142
+ this.setScreenTransform_();
2143
+ if (isLandscapeMode()) {
2144
+ this.filterToWorldQ.multiply(this.inverseWorldToScreenQ);
2145
+ }
2146
+ this.resetQ = new Quaternion();
2147
+ this.orientationOut_ = new Float32Array(4);
2148
+ this.start();
2149
+ }
2150
+ FusionPoseSensor.prototype.getPosition = function () {
2151
+ return null;
2152
+ };
2153
+ FusionPoseSensor.prototype.getOrientation = function () {
2154
+ var orientation = void 0;
2155
+ if (this.isWithoutDeviceMotion && this._deviceOrientationQ) {
2156
+ this.deviceOrientationFixQ = this.deviceOrientationFixQ || function () {
2157
+ var z = new Quaternion().setFromAxisAngle(new Vector3(0, 0, -1), 0);
2158
+ var y = new Quaternion();
2159
+ if (window.orientation === -90) {
2160
+ y.setFromAxisAngle(new Vector3(0, 1, 0), Math.PI / -2);
2161
+ } else {
2162
+ y.setFromAxisAngle(new Vector3(0, 1, 0), Math.PI / 2);
2163
+ }
2164
+ return z.multiply(y);
2165
+ }();
2166
+ this.deviceOrientationFilterToWorldQ = this.deviceOrientationFilterToWorldQ || function () {
2167
+ var q = new Quaternion();
2168
+ q.setFromAxisAngle(new Vector3(1, 0, 0), -Math.PI / 2);
2169
+ return q;
2170
+ }();
2171
+ orientation = this._deviceOrientationQ;
2172
+ var out = new Quaternion();
2173
+ out.copy(orientation);
2174
+ out.multiply(this.deviceOrientationFilterToWorldQ);
2175
+ out.multiply(this.resetQ);
2176
+ out.multiply(this.worldToScreenQ);
2177
+ out.multiplyQuaternions(this.deviceOrientationFixQ, out);
2178
+ if (this.yawOnly) {
2179
+ out.x = 0;
2180
+ out.z = 0;
2181
+ out.normalize();
2182
+ }
2183
+ this.orientationOut_[0] = out.x;
2184
+ this.orientationOut_[1] = out.y;
2185
+ this.orientationOut_[2] = out.z;
2186
+ this.orientationOut_[3] = out.w;
2187
+ return this.orientationOut_;
2188
+ } else {
2189
+ var filterOrientation = this.filter.getOrientation();
2190
+ orientation = this.posePredictor.getPrediction(filterOrientation, this.gyroscope, this.previousTimestampS);
2191
+ }
2192
+ var out = new Quaternion();
2193
+ out.copy(this.filterToWorldQ);
2194
+ out.multiply(this.resetQ);
2195
+ out.multiply(orientation);
2196
+ out.multiply(this.worldToScreenQ);
2197
+ if (this.yawOnly) {
2198
+ out.x = 0;
2199
+ out.z = 0;
2200
+ out.normalize();
2201
+ }
2202
+ this.orientationOut_[0] = out.x;
2203
+ this.orientationOut_[1] = out.y;
2204
+ this.orientationOut_[2] = out.z;
2205
+ this.orientationOut_[3] = out.w;
2206
+ return this.orientationOut_;
2207
+ };
2208
+ FusionPoseSensor.prototype.resetPose = function () {
2209
+ this.resetQ.copy(this.filter.getOrientation());
2210
+ this.resetQ.x = 0;
2211
+ this.resetQ.y = 0;
2212
+ this.resetQ.z *= -1;
2213
+ this.resetQ.normalize();
2214
+ if (isLandscapeMode()) {
2215
+ this.resetQ.multiply(this.inverseWorldToScreenQ);
2216
+ }
2217
+ this.resetQ.multiply(this.originalPoseAdjustQ);
2218
+ };
2219
+ FusionPoseSensor.prototype.onDeviceOrientation_ = function (e) {
2220
+ this._deviceOrientationQ = this._deviceOrientationQ || new Quaternion();
2221
+ var alpha = e.alpha,
2222
+ beta = e.beta,
2223
+ gamma = e.gamma;
2224
+ alpha = (alpha || 0) * Math.PI / 180;
2225
+ beta = (beta || 0) * Math.PI / 180;
2226
+ gamma = (gamma || 0) * Math.PI / 180;
2227
+ this._deviceOrientationQ.setFromEulerYXZ(beta, alpha, -gamma);
2228
+ };
2229
+ FusionPoseSensor.prototype.onDeviceMotion_ = function (deviceMotion) {
2230
+ this.updateDeviceMotion_(deviceMotion);
2231
+ };
2232
+ FusionPoseSensor.prototype.updateDeviceMotion_ = function (deviceMotion) {
2233
+ var accGravity = deviceMotion.accelerationIncludingGravity;
2234
+ var rotRate = deviceMotion.rotationRate;
2235
+ var timestampS = deviceMotion.timeStamp / 1000;
2236
+ var deltaS = timestampS - this.previousTimestampS;
2237
+ if (deltaS < 0) {
2238
+ warnOnce('fusion-pose-sensor:invalid:non-monotonic', 'Invalid timestamps detected: non-monotonic timestamp from devicemotion');
2239
+ this.previousTimestampS = timestampS;
2240
+ return;
2241
+ } else if (deltaS <= MIN_TIMESTEP || deltaS > MAX_TIMESTEP) {
2242
+ warnOnce('fusion-pose-sensor:invalid:outside-threshold', 'Invalid timestamps detected: Timestamp from devicemotion outside expected range.');
2243
+ this.previousTimestampS = timestampS;
2244
+ return;
2245
+ }
2246
+ this.accelerometer.set(-accGravity.x, -accGravity.y, -accGravity.z);
2247
+ if (isR7()) {
2248
+ this.gyroscope.set(-rotRate.beta, rotRate.alpha, rotRate.gamma);
2249
+ } else {
2250
+ this.gyroscope.set(rotRate.alpha, rotRate.beta, rotRate.gamma);
2251
+ }
2252
+ if (!this.isDeviceMotionInRadians) {
2253
+ this.gyroscope.multiplyScalar(Math.PI / 180);
2254
+ }
2255
+ this.filter.addAccelMeasurement(this.accelerometer, timestampS);
2256
+ this.filter.addGyroMeasurement(this.gyroscope, timestampS);
2257
+ this.previousTimestampS = timestampS;
2258
+ };
2259
+ FusionPoseSensor.prototype.onOrientationChange_ = function (screenOrientation) {
2260
+ this.setScreenTransform_();
2261
+ };
2262
+ FusionPoseSensor.prototype.onMessage_ = function (event) {
2263
+ var message = event.data;
2264
+ if (!message || !message.type) {
2265
+ return;
2266
+ }
2267
+ var type = message.type.toLowerCase();
2268
+ if (type !== 'devicemotion') {
2269
+ return;
2270
+ }
2271
+ this.updateDeviceMotion_(message.deviceMotionEvent);
2272
+ };
2273
+ FusionPoseSensor.prototype.setScreenTransform_ = function () {
2274
+ this.worldToScreenQ.set(0, 0, 0, 1);
2275
+ switch (window.orientation) {
2276
+ case 0:
2277
+ break;
2278
+ case 90:
2279
+ this.worldToScreenQ.setFromAxisAngle(new Vector3(0, 0, 1), -Math.PI / 2);
2280
+ break;
2281
+ case -90:
2282
+ this.worldToScreenQ.setFromAxisAngle(new Vector3(0, 0, 1), Math.PI / 2);
2283
+ break;
2284
+ case 180:
2285
+ break;
2286
+ }
2287
+ this.inverseWorldToScreenQ.copy(this.worldToScreenQ);
2288
+ this.inverseWorldToScreenQ.inverse();
2289
+ };
2290
+ FusionPoseSensor.prototype.start = function () {
2291
+ this.onDeviceMotionCallback_ = this.onDeviceMotion_.bind(this);
2292
+ this.onOrientationChangeCallback_ = this.onOrientationChange_.bind(this);
2293
+ this.onMessageCallback_ = this.onMessage_.bind(this);
2294
+ this.onDeviceOrientationCallback_ = this.onDeviceOrientation_.bind(this);
2295
+ if (isIOS() && isInsideCrossOriginIFrame()) {
2296
+ window.addEventListener('message', this.onMessageCallback_);
2297
+ }
2298
+ window.addEventListener('orientationchange', this.onOrientationChangeCallback_);
2299
+ if (this.isWithoutDeviceMotion) {
2300
+ window.addEventListener('deviceorientation', this.onDeviceOrientationCallback_);
2301
+ } else {
2302
+ window.addEventListener('devicemotion', this.onDeviceMotionCallback_);
2303
+ }
2304
+ };
2305
+ FusionPoseSensor.prototype.stop = function () {
2306
+ window.removeEventListener('devicemotion', this.onDeviceMotionCallback_);
2307
+ window.removeEventListener('deviceorientation', this.onDeviceOrientationCallback_);
2308
+ window.removeEventListener('orientationchange', this.onOrientationChangeCallback_);
2309
+ window.removeEventListener('message', this.onMessageCallback_);
2310
+ };
2311
+ var SENSOR_FREQUENCY = 60;
2312
+ var X_AXIS = new Vector3(1, 0, 0);
2313
+ var Z_AXIS = new Vector3(0, 0, 1);
2314
+ var SENSOR_TO_VR = new Quaternion();
2315
+ SENSOR_TO_VR.setFromAxisAngle(X_AXIS, -Math.PI / 2);
2316
+ SENSOR_TO_VR.multiply(new Quaternion().setFromAxisAngle(Z_AXIS, Math.PI / 2));
2317
+ var PoseSensor = function () {
2318
+ function PoseSensor(config) {
2319
+ classCallCheck(this, PoseSensor);
2320
+ this.config = config;
2321
+ this.sensor = null;
2322
+ this.fusionSensor = null;
2323
+ this._out = new Float32Array(4);
2324
+ this.api = null;
2325
+ this.errors = [];
2326
+ this._sensorQ = new Quaternion();
2327
+ this._outQ = new Quaternion();
2328
+ this._onSensorRead = this._onSensorRead.bind(this);
2329
+ this._onSensorError = this._onSensorError.bind(this);
2330
+ this.init();
2331
+ }
2332
+ createClass(PoseSensor, [{
2333
+ key: 'init',
2334
+ value: function init() {
2335
+ var sensor = null;
2336
+ try {
2337
+ sensor = new RelativeOrientationSensor({
2338
+ frequency: SENSOR_FREQUENCY,
2339
+ referenceFrame: 'screen'
2340
+ });
2341
+ sensor.addEventListener('error', this._onSensorError);
2342
+ } catch (error) {
2343
+ this.errors.push(error);
2344
+ if (error.name === 'SecurityError') {
2345
+ console.error('Cannot construct sensors due to the Feature Policy');
2346
+ console.warn('Attempting to fall back using "devicemotion"; however this will ' + 'fail in the future without correct permissions.');
2347
+ this.useDeviceMotion();
2348
+ } else if (error.name === 'ReferenceError') {
2349
+ this.useDeviceMotion();
2350
+ } else {
2351
+ console.error(error);
2352
+ }
2353
+ }
2354
+ if (sensor) {
2355
+ this.api = 'sensor';
2356
+ this.sensor = sensor;
2357
+ this.sensor.addEventListener('reading', this._onSensorRead);
2358
+ this.sensor.start();
2359
+ }
2360
+ }
2361
+ }, {
2362
+ key: 'useDeviceMotion',
2363
+ value: function useDeviceMotion() {
2364
+ this.api = 'devicemotion';
2365
+ this.fusionSensor = new FusionPoseSensor(this.config.K_FILTER, this.config.PREDICTION_TIME_S, this.config.YAW_ONLY, this.config.DEBUG);
2366
+ if (this.sensor) {
2367
+ this.sensor.removeEventListener('reading', this._onSensorRead);
2368
+ this.sensor.removeEventListener('error', this._onSensorError);
2369
+ this.sensor = null;
2370
+ }
2371
+ }
2372
+ }, {
2373
+ key: 'getOrientation',
2374
+ value: function getOrientation() {
2375
+ if (this.fusionSensor) {
2376
+ return this.fusionSensor.getOrientation();
2377
+ }
2378
+ if (!this.sensor || !this.sensor.quaternion) {
2379
+ this._out[0] = this._out[1] = this._out[2] = 0;
2380
+ this._out[3] = 1;
2381
+ return this._out;
2382
+ }
2383
+ var q = this.sensor.quaternion;
2384
+ this._sensorQ.set(q[0], q[1], q[2], q[3]);
2385
+ var out = this._outQ;
2386
+ out.copy(SENSOR_TO_VR);
2387
+ out.multiply(this._sensorQ);
2388
+ if (this.config.YAW_ONLY) {
2389
+ out.x = out.z = 0;
2390
+ out.normalize();
2391
+ }
2392
+ this._out[0] = out.x;
2393
+ this._out[1] = out.y;
2394
+ this._out[2] = out.z;
2395
+ this._out[3] = out.w;
2396
+ return this._out;
2397
+ }
2398
+ }, {
2399
+ key: '_onSensorError',
2400
+ value: function _onSensorError(event) {
2401
+ this.errors.push(event.error);
2402
+ if (event.error.name === 'NotAllowedError') {
2403
+ console.error('Permission to access sensor was denied');
2404
+ } else if (event.error.name === 'NotReadableError') {
2405
+ console.error('Sensor could not be read');
2406
+ } else {
2407
+ console.error(event.error);
2408
+ }
2409
+ this.useDeviceMotion();
2410
+ }
2411
+ }, {
2412
+ key: '_onSensorRead',
2413
+ value: function _onSensorRead() {}
2414
+ }]);
2415
+ return PoseSensor;
2416
+ }();
2417
+ var rotateInstructionsAsset = 'PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+Cjxzdmcgd2lkdGg9IjE5OHB4IiBoZWlnaHQ9IjI0MHB4IiB2aWV3Qm94PSIwIDAgMTk4IDI0MCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4bWxuczpza2V0Y2g9Imh0dHA6Ly93d3cuYm9oZW1pYW5jb2RpbmcuY29tL3NrZXRjaC9ucyI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDMuMy4zICgxMjA4MSkgLSBodHRwOi8vd3d3LmJvaGVtaWFuY29kaW5nLmNvbS9za2V0Y2ggLS0+CiAgICA8dGl0bGU+dHJhbnNpdGlvbjwvdGl0bGU+CiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggU2tldGNoLjwvZGVzYz4KICAgIDxkZWZzPjwvZGVmcz4KICAgIDxnIGlkPSJQYWdlLTEiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIHNrZXRjaDp0eXBlPSJNU1BhZ2UiPgogICAgICAgIDxnIGlkPSJ0cmFuc2l0aW9uIiBza2V0Y2g6dHlwZT0iTVNBcnRib2FyZEdyb3VwIj4KICAgICAgICAgICAgPGcgaWQ9IkltcG9ydGVkLUxheWVycy1Db3B5LTQtKy1JbXBvcnRlZC1MYXllcnMtQ29weS0rLUltcG9ydGVkLUxheWVycy1Db3B5LTItQ29weSIgc2tldGNoOnR5cGU9Ik1TTGF5ZXJHcm91cCI+CiAgICAgICAgICAgICAgICA8ZyBpZD0iSW1wb3J0ZWQtTGF5ZXJzLUNvcHktNCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMC4wMDAwMDAsIDEwNy4wMDAwMDApIiBza2V0Y2g6dHlwZT0iTVNTaGFwZUdyb3VwIj4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTQ5LjYyNSwyLjUyNyBDMTQ5LjYyNSwyLjUyNyAxNTUuODA1LDYuMDk2IDE1Ni4zNjIsNi40MTggTDE1Ni4zNjIsNy4zMDQgQzE1Ni4zNjIsNy40ODEgMTU2LjM3NSw3LjY2NCAxNTYuNCw3Ljg1MyBDMTU2LjQxLDcuOTM0IDE1Ni40Miw4LjAxNSAxNTYuNDI3LDguMDk1IEMxNTYuNTY3LDkuNTEgMTU3LjQwMSwxMS4wOTMgMTU4LjUzMiwxMi4wOTQgTDE2NC4yNTIsMTcuMTU2IEwxNjQuMzMzLDE3LjA2NiBDMTY0LjMzMywxNy4wNjYgMTY4LjcxNSwxNC41MzYgMTY5LjU2OCwxNC4wNDIgQzE3MS4wMjUsMTQuODgzIDE5NS41MzgsMjkuMDM1IDE5NS41MzgsMjkuMDM1IEwxOTUuNTM4LDgzLjAzNiBDMTk1LjUzOCw4My44MDcgMTk1LjE1Miw4NC4yNTMgMTk0LjU5LDg0LjI1MyBDMTk0LjM1Nyw4NC4yNTMgMTk0LjA5NSw4NC4xNzcgMTkzLjgxOCw4NC4wMTcgTDE2OS44NTEsNzAuMTc5IEwxNjkuODM3LDcwLjIwMyBMMTQyLjUxNSw4NS45NzggTDE0MS42NjUsODQuNjU1IEMxMzYuOTM0LDgzLjEyNiAxMzEuOTE3LDgxLjkxNSAxMjYuNzE0LDgxLjA0NSBDMTI2LjcwOSw4MS4wNiAxMjYuNzA3LDgxLjA2OSAxMjYuNzA3LDgxLjA2OSBMMTIxLjY0LDk4LjAzIEwxMTMuNzQ5LDEwMi41ODYgTDExMy43MTIsMTAyLjUyMyBMMTEzLjcxMiwxMzAuMTEzIEMxMTMuNzEyLDEzMC44ODUgMTEzLjMyNiwxMzEuMzMgMTEyLjc2NCwxMzEuMzMgQzExMi41MzIsMTMxLjMzIDExMi4yNjksMTMxLjI1NCAxMTEuOTkyLDEzMS4wOTQgTDY5LjUxOSwxMDYuNTcyIEM2OC41NjksMTA2LjAyMyA2Ny43OTksMTA0LjY5NSA2Ny43OTksMTAzLjYwNSBMNjcuNzk5LDEwMi41NyBMNjcuNzc4LDEwMi42MTcgQzY3LjI3LDEwMi4zOTMgNjYuNjQ4LDEwMi4yNDkgNjUuOTYyLDEwMi4yMTggQzY1Ljg3NSwxMDIuMjE0IDY1Ljc4OCwxMDIuMjEyIDY1LjcwMSwxMDIuMjEyIEM2NS42MDYsMTAyLjIxMiA2NS41MTEsMTAyLjIxNSA2NS40MTYsMTAyLjIxOSBDNjUuMTk1LDEwMi4yMjkgNjQuOTc0LDEwMi4yMzUgNjQuNzU0LDEwMi4yMzUgQzY0LjMzMSwxMDIuMjM1IDYzLjkxMSwxMDIuMjE2IDYzLjQ5OCwxMDIuMTc4IEM2MS44NDMsMTAyLjAyNSA2MC4yOTgsMTAxLjU3OCA1OS4wOTQsMTAwLjg4MiBMMTIuNTE4LDczLjk5MiBMMTIuNTIzLDc0LjAwNCBMMi4yNDUsNTUuMjU0IEMxLjI0NCw1My40MjcgMi4wMDQsNTEuMDM4IDMuOTQzLDQ5LjkxOCBMNTkuOTU0LDE3LjU3MyBDNjAuNjI2LDE3LjE4NSA2MS4zNSwxNy4wMDEgNjIuMDUzLDE3LjAwMSBDNjMuMzc5LDE3LjAwMSA2NC42MjUsMTcuNjYgNjUuMjgsMTguODU0IEw2NS4yODUsMTguODUxIEw2NS41MTIsMTkuMjY0IEw2NS41MDYsMTkuMjY4IEM2NS45MDksMjAuMDAzIDY2LjQwNSwyMC42OCA2Ni45ODMsMjEuMjg2IEw2Ny4yNiwyMS41NTYgQzY5LjE3NCwyMy40MDYgNzEuNzI4LDI0LjM1NyA3NC4zNzMsMjQuMzU3IEM3Ni4zMjIsMjQuMzU3IDc4LjMyMSwyMy44NCA4MC4xNDgsMjIuNzg1IEM4MC4xNjEsMjIuNzg1IDg3LjQ2NywxOC41NjYgODcuNDY3LDE4LjU2NiBDODguMTM5LDE4LjE3OCA4OC44NjMsMTcuOTk0IDg5LjU2NiwxNy45OTQgQzkwLjg5MiwxNy45OTQgOTIuMTM4LDE4LjY1MiA5Mi43OTIsMTkuODQ3IEw5Ni4wNDIsMjUuNzc1IEw5Ni4wNjQsMjUuNzU3IEwxMDIuODQ5LDI5LjY3NCBMMTAyLjc0NCwyOS40OTIgTDE0OS42MjUsMi41MjcgTTE0OS42MjUsMC44OTIgQzE0OS4zNDMsMC44OTIgMTQ5LjA2MiwwLjk2NSAxNDguODEsMS4xMSBMMTAyLjY0MSwyNy42NjYgTDk3LjIzMSwyNC41NDIgTDk0LjIyNiwxOS4wNjEgQzkzLjMxMywxNy4zOTQgOTEuNTI3LDE2LjM1OSA4OS41NjYsMTYuMzU4IEM4OC41NTUsMTYuMzU4IDg3LjU0NiwxNi42MzIgODYuNjQ5LDE3LjE1IEM4My44NzgsMTguNzUgNzkuNjg3LDIxLjE2OSA3OS4zNzQsMjEuMzQ1IEM3OS4zNTksMjEuMzUzIDc5LjM0NSwyMS4zNjEgNzkuMzMsMjEuMzY5IEM3Ny43OTgsMjIuMjU0IDc2LjA4NCwyMi43MjIgNzQuMzczLDIyLjcyMiBDNzIuMDgxLDIyLjcyMiA2OS45NTksMjEuODkgNjguMzk3LDIwLjM4IEw2OC4xNDUsMjAuMTM1IEM2Ny43MDYsMTkuNjcyIDY3LjMyMywxOS4xNTYgNjcuMDA2LDE4LjYwMSBDNjYuOTg4LDE4LjU1OSA2Ni45NjgsMTguNTE5IDY2Ljk0NiwxOC40NzkgTDY2LjcxOSwxOC4wNjUgQzY2LjY5LDE4LjAxMiA2Ni42NTgsMTcuOTYgNjYuNjI0LDE3LjkxMSBDNjUuNjg2LDE2LjMzNyA2My45NTEsMTUuMzY2IDYyLjA1MywxNS4zNjYgQzYxLjA0MiwxNS4zNjYgNjAuMDMzLDE1LjY0IDU5LjEzNiwxNi4xNTggTDMuMTI1LDQ4LjUwMiBDMC40MjYsNTAuMDYxIC0wLjYxMyw1My40NDIgMC44MTEsNTYuMDQgTDExLjA4OSw3NC43OSBDMTEuMjY2LDc1LjExMyAxMS41MzcsNzUuMzUzIDExLjg1LDc1LjQ5NCBMNTguMjc2LDEwMi4yOTggQzU5LjY3OSwxMDMuMTA4IDYxLjQzMywxMDMuNjMgNjMuMzQ4LDEwMy44MDYgQzYzLjgxMiwxMDMuODQ4IDY0LjI4NSwxMDMuODcgNjQuNzU0LDEwMy44NyBDNjUsMTAzLjg3IDY1LjI0OSwxMDMuODY0IDY1LjQ5NCwxMDMuODUyIEM2NS41NjMsMTAzLjg0OSA2NS42MzIsMTAzLjg0NyA2NS43MDEsMTAzLjg0NyBDNjUuNzY0LDEwMy44NDcgNjUuODI4LDEwMy44NDkgNjUuODksMTAzLjg1MiBDNjUuOTg2LDEwMy44NTYgNjYuMDgsMTAzLjg2MyA2Ni4xNzMsMTAzLjg3NCBDNjYuMjgyLDEwNS40NjcgNjcuMzMyLDEwNy4xOTcgNjguNzAyLDEwNy45ODggTDExMS4xNzQsMTMyLjUxIEMxMTEuNjk4LDEzMi44MTIgMTEyLjIzMiwxMzIuOTY1IDExMi43NjQsMTMyLjk2NSBDMTE0LjI2MSwxMzIuOTY1IDExNS4zNDcsMTMxLjc2NSAxMTUuMzQ3LDEzMC4xMTMgTDExNS4zNDcsMTAzLjU1MSBMMTIyLjQ1OCw5OS40NDYgQzEyMi44MTksOTkuMjM3IDEyMy4wODcsOTguODk4IDEyMy4yMDcsOTguNDk4IEwxMjcuODY1LDgyLjkwNSBDMTMyLjI3OSw4My43MDIgMTM2LjU1Nyw4NC43NTMgMTQwLjYwNyw4Ni4wMzMgTDE0MS4xNCw4Ni44NjIgQzE0MS40NTEsODcuMzQ2IDE0MS45NzcsODcuNjEzIDE0Mi41MTYsODcuNjEzIEMxNDIuNzk0LDg3LjYxMyAxNDMuMDc2LDg3LjU0MiAxNDMuMzMzLDg3LjM5MyBMMTY5Ljg2NSw3Mi4wNzYgTDE5Myw4NS40MzMgQzE5My41MjMsODUuNzM1IDE5NC4wNTgsODUuODg4IDE5NC41OSw4NS44ODggQzE5Ni4wODcsODUuODg4IDE5Ny4xNzMsODQuNjg5IDE5Ny4xNzMsODMuMDM2IEwxOTcuMTczLDI5LjAzNSBDMTk3LjE3MywyOC40NTEgMTk2Ljg2MSwyNy45MTEgMTk2LjM1NSwyNy42MTkgQzE5Ni4zNTUsMjcuNjE5IDE3MS44NDMsMTMuNDY3IDE3MC4zODUsMTIuNjI2IEMxNzAuMTMyLDEyLjQ4IDE2OS44NSwxMi40MDcgMTY5LjU2OCwxMi40MDcgQzE2OS4yODUsMTIuNDA3IDE2OS4wMDIsMTIuNDgxIDE2OC43NDksMTIuNjI3IEMxNjguMTQzLDEyLjk3OCAxNjUuNzU2LDE0LjM1NyAxNjQuNDI0LDE1LjEyNSBMMTU5LjYxNSwxMC44NyBDMTU4Ljc5NiwxMC4xNDUgMTU4LjE1NCw4LjkzNyAxNTguMDU0LDcuOTM0IEMxNTguMDQ1LDcuODM3IDE1OC4wMzQsNy43MzkgMTU4LjAyMSw3LjY0IEMxNTguMDA1LDcuNTIzIDE1Ny45OTgsNy40MSAxNTcuOTk4LDcuMzA0IEwxNTcuOTk4LDYuNDE4IEMxNTcuOTk4LDUuODM0IDE1Ny42ODYsNS4yOTUgMTU3LjE4MSw1LjAwMiBDMTU2LjYyNCw0LjY4IDE1MC40NDIsMS4xMTEgMTUwLjQ0MiwxLjExMSBDMTUwLjE4OSwwLjk2NSAxNDkuOTA3LDAuODkyIDE0OS42MjUsMC44OTIiIGlkPSJGaWxsLTEiIGZpbGw9IiM0NTVBNjQiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNOTYuMDI3LDI1LjYzNiBMMTQyLjYwMyw1Mi41MjcgQzE0My44MDcsNTMuMjIyIDE0NC41ODIsNTQuMTE0IDE0NC44NDUsNTUuMDY4IEwxNDQuODM1LDU1LjA3NSBMNjMuNDYxLDEwMi4wNTcgTDYzLjQ2LDEwMi4wNTcgQzYxLjgwNiwxMDEuOTA1IDYwLjI2MSwxMDEuNDU3IDU5LjA1NywxMDAuNzYyIEwxMi40ODEsNzMuODcxIEw5Ni4wMjcsMjUuNjM2IiBpZD0iRmlsbC0yIiBmaWxsPSIjRkFGQUZBIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTYzLjQ2MSwxMDIuMTc0IEM2My40NTMsMTAyLjE3NCA2My40NDYsMTAyLjE3NCA2My40MzksMTAyLjE3MiBDNjEuNzQ2LDEwMi4wMTYgNjAuMjExLDEwMS41NjMgNTguOTk4LDEwMC44NjMgTDEyLjQyMiw3My45NzMgQzEyLjM4Niw3My45NTIgMTIuMzY0LDczLjkxNCAxMi4zNjQsNzMuODcxIEMxMi4zNjQsNzMuODMgMTIuMzg2LDczLjc5MSAxMi40MjIsNzMuNzcgTDk1Ljk2OCwyNS41MzUgQzk2LjAwNCwyNS41MTQgOTYuMDQ5LDI1LjUxNCA5Ni4wODUsMjUuNTM1IEwxNDIuNjYxLDUyLjQyNiBDMTQzLjg4OCw1My4xMzQgMTQ0LjY4Miw1NC4wMzggMTQ0Ljk1Nyw1NS4wMzcgQzE0NC45Nyw1NS4wODMgMTQ0Ljk1Myw1NS4xMzMgMTQ0LjkxNSw1NS4xNjEgQzE0NC45MTEsNTUuMTY1IDE0NC44OTgsNTUuMTc0IDE0NC44OTQsNTUuMTc3IEw2My41MTksMTAyLjE1OCBDNjMuNTAxLDEwMi4xNjkgNjMuNDgxLDEwMi4xNzQgNjMuNDYxLDEwMi4xNzQgTDYzLjQ2MSwxMDIuMTc0IFogTTEyLjcxNCw3My44NzEgTDU5LjExNSwxMDAuNjYxIEM2MC4yOTMsMTAxLjM0MSA2MS43ODYsMTAxLjc4MiA2My40MzUsMTAxLjkzNyBMMTQ0LjcwNyw1NS4wMTUgQzE0NC40MjgsNTQuMTA4IDE0My42ODIsNTMuMjg1IDE0Mi41NDQsNTIuNjI4IEw5Ni4wMjcsMjUuNzcxIEwxMi43MTQsNzMuODcxIEwxMi43MTQsNzMuODcxIFoiIGlkPSJGaWxsLTMiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTQ4LjMyNyw1OC40NzEgQzE0OC4xNDUsNTguNDggMTQ3Ljk2Miw1OC40OCAxNDcuNzgxLDU4LjQ3MiBDMTQ1Ljg4Nyw1OC4zODkgMTQ0LjQ3OSw1Ny40MzQgMTQ0LjYzNiw1Ni4zNCBDMTQ0LjY4OSw1NS45NjcgMTQ0LjY2NCw1NS41OTcgMTQ0LjU2NCw1NS4yMzUgTDYzLjQ2MSwxMDIuMDU3IEM2NC4wODksMTAyLjExNSA2NC43MzMsMTAyLjEzIDY1LjM3OSwxMDIuMDk5IEM2NS41NjEsMTAyLjA5IDY1Ljc0MywxMDIuMDkgNjUuOTI1LDEwMi4wOTggQzY3LjgxOSwxMDIuMTgxIDY5LjIyNywxMDMuMTM2IDY5LjA3LDEwNC4yMyBMMTQ4LjMyNyw1OC40NzEiIGlkPSJGaWxsLTQiIGZpbGw9IiNGRkZGRkYiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNNjkuMDcsMTA0LjM0NyBDNjkuMDQ4LDEwNC4zNDcgNjkuMDI1LDEwNC4zNCA2OS4wMDUsMTA0LjMyNyBDNjguOTY4LDEwNC4zMDEgNjguOTQ4LDEwNC4yNTcgNjguOTU1LDEwNC4yMTMgQzY5LDEwMy44OTYgNjguODk4LDEwMy41NzYgNjguNjU4LDEwMy4yODggQzY4LjE1MywxMDIuNjc4IDY3LjEwMywxMDIuMjY2IDY1LjkyLDEwMi4yMTQgQzY1Ljc0MiwxMDIuMjA2IDY1LjU2MywxMDIuMjA3IDY1LjM4NSwxMDIuMjE1IEM2NC43NDIsMTAyLjI0NiA2NC4wODcsMTAyLjIzMiA2My40NSwxMDIuMTc0IEM2My4zOTksMTAyLjE2OSA2My4zNTgsMTAyLjEzMiA2My4zNDcsMTAyLjA4MiBDNjMuMzM2LDEwMi4wMzMgNjMuMzU4LDEwMS45ODEgNjMuNDAyLDEwMS45NTYgTDE0NC41MDYsNTUuMTM0IEMxNDQuNTM3LDU1LjExNiAxNDQuNTc1LDU1LjExMyAxNDQuNjA5LDU1LjEyNyBDMTQ0LjY0Miw1NS4xNDEgMTQ0LjY2OCw1NS4xNyAxNDQuNjc3LDU1LjIwNCBDMTQ0Ljc4MSw1NS41ODUgMTQ0LjgwNiw1NS45NzIgMTQ0Ljc1MSw1Ni4zNTcgQzE0NC43MDYsNTYuNjczIDE0NC44MDgsNTYuOTk0IDE0NS4wNDcsNTcuMjgyIEMxNDUuNTUzLDU3Ljg5MiAxNDYuNjAyLDU4LjMwMyAxNDcuNzg2LDU4LjM1NSBDMTQ3Ljk2NCw1OC4zNjMgMTQ4LjE0Myw1OC4zNjMgMTQ4LjMyMSw1OC4zNTQgQzE0OC4zNzcsNTguMzUyIDE0OC40MjQsNTguMzg3IDE0OC40MzksNTguNDM4IEMxNDguNDU0LDU4LjQ5IDE0OC40MzIsNTguNTQ1IDE0OC4zODUsNTguNTcyIEw2OS4xMjksMTA0LjMzMSBDNjkuMTExLDEwNC4zNDIgNjkuMDksMTA0LjM0NyA2OS4wNywxMDQuMzQ3IEw2OS4wNywxMDQuMzQ3IFogTTY1LjY2NSwxMDEuOTc1IEM2NS43NTQsMTAxLjk3NSA2NS44NDIsMTAxLjk3NyA2NS45MywxMDEuOTgxIEM2Ny4xOTYsMTAyLjAzNyA2OC4yODMsMTAyLjQ2OSA2OC44MzgsMTAzLjEzOSBDNjkuMDY1LDEwMy40MTMgNjkuMTg4LDEwMy43MTQgNjkuMTk4LDEwNC4wMjEgTDE0Ny44ODMsNTguNTkyIEMxNDcuODQ3LDU4LjU5MiAxNDcuODExLDU4LjU5MSAxNDcuNzc2LDU4LjU4OSBDMTQ2LjUwOSw1OC41MzMgMTQ1LjQyMiw1OC4xIDE0NC44NjcsNTcuNDMxIEMxNDQuNTg1LDU3LjA5MSAxNDQuNDY1LDU2LjcwNyAxNDQuNTIsNTYuMzI0IEMxNDQuNTYzLDU2LjAyMSAxNDQuNTUyLDU1LjcxNiAxNDQuNDg4LDU1LjQxNCBMNjMuODQ2LDEwMS45NyBDNjQuMzUzLDEwMi4wMDIgNjQuODY3LDEwMi4wMDYgNjUuMzc0LDEwMS45ODIgQzY1LjQ3MSwxMDEuOTc3IDY1LjU2OCwxMDEuOTc1IDY1LjY2NSwxMDEuOTc1IEw2NS42NjUsMTAxLjk3NSBaIiBpZD0iRmlsbC01IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTIuMjA4LDU1LjEzNCBDMS4yMDcsNTMuMzA3IDEuOTY3LDUwLjkxNyAzLjkwNiw0OS43OTcgTDU5LjkxNywxNy40NTMgQzYxLjg1NiwxNi4zMzMgNjQuMjQxLDE2LjkwNyA2NS4yNDMsMTguNzM0IEw2NS40NzUsMTkuMTQ0IEM2NS44NzIsMTkuODgyIDY2LjM2OCwyMC41NiA2Ni45NDUsMjEuMTY1IEw2Ny4yMjMsMjEuNDM1IEM3MC41NDgsMjQuNjQ5IDc1LjgwNiwyNS4xNTEgODAuMTExLDIyLjY2NSBMODcuNDMsMTguNDQ1IEM4OS4zNywxNy4zMjYgOTEuNzU0LDE3Ljg5OSA5Mi43NTUsMTkuNzI3IEw5Ni4wMDUsMjUuNjU1IEwxMi40ODYsNzMuODg0IEwyLjIwOCw1NS4xMzQgWiIgaWQ9IkZpbGwtNiIgZmlsbD0iI0ZBRkFGQSI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xMi40ODYsNzQuMDAxIEMxMi40NzYsNzQuMDAxIDEyLjQ2NSw3My45OTkgMTIuNDU1LDczLjk5NiBDMTIuNDI0LDczLjk4OCAxMi4zOTksNzMuOTY3IDEyLjM4NCw3My45NCBMMi4xMDYsNTUuMTkgQzEuMDc1LDUzLjMxIDEuODU3LDUwLjg0NSAzLjg0OCw0OS42OTYgTDU5Ljg1OCwxNy4zNTIgQzYwLjUyNSwxNi45NjcgNjEuMjcxLDE2Ljc2NCA2Mi4wMTYsMTYuNzY0IEM2My40MzEsMTYuNzY0IDY0LjY2NiwxNy40NjYgNjUuMzI3LDE4LjY0NiBDNjUuMzM3LDE4LjY1NCA2NS4zNDUsMTguNjYzIDY1LjM1MSwxOC42NzQgTDY1LjU3OCwxOS4wODggQzY1LjU4NCwxOS4xIDY1LjU4OSwxOS4xMTIgNjUuNTkxLDE5LjEyNiBDNjUuOTg1LDE5LjgzOCA2Ni40NjksMjAuNDk3IDY3LjAzLDIxLjA4NSBMNjcuMzA1LDIxLjM1MSBDNjkuMTUxLDIzLjEzNyA3MS42NDksMjQuMTIgNzQuMzM2LDI0LjEyIEM3Ni4zMTMsMjQuMTIgNzguMjksMjMuNTgyIDgwLjA1MywyMi41NjMgQzgwLjA2NCwyMi41NTcgODAuMDc2LDIyLjU1MyA4MC4wODgsMjIuNTUgTDg3LjM3MiwxOC4zNDQgQzg4LjAzOCwxNy45NTkgODguNzg0LDE3Ljc1NiA4OS41MjksMTcuNzU2IEM5MC45NTYsMTcuNzU2IDkyLjIwMSwxOC40NzIgOTIuODU4LDE5LjY3IEw5Ni4xMDcsMjUuNTk5IEM5Ni4xMzgsMjUuNjU0IDk2LjExOCwyNS43MjQgOTYuMDYzLDI1Ljc1NiBMMTIuNTQ1LDczLjk4NSBDMTIuNTI2LDczLjk5NiAxMi41MDYsNzQuMDAxIDEyLjQ4Niw3NC4wMDEgTDEyLjQ4Niw3NC4wMDEgWiBNNjIuMDE2LDE2Ljk5NyBDNjEuMzEyLDE2Ljk5NyA2MC42MDYsMTcuMTkgNTkuOTc1LDE3LjU1NCBMMy45NjUsNDkuODk5IEMyLjA4Myw1MC45ODUgMS4zNDEsNTMuMzA4IDIuMzEsNTUuMDc4IEwxMi41MzEsNzMuNzIzIEw5NS44NDgsMjUuNjExIEw5Mi42NTMsMTkuNzgyIEM5Mi4wMzgsMTguNjYgOTAuODcsMTcuOTkgODkuNTI5LDE3Ljk5IEM4OC44MjUsMTcuOTkgODguMTE5LDE4LjE4MiA4Ny40ODksMTguNTQ3IEw4MC4xNzIsMjIuNzcyIEM4MC4xNjEsMjIuNzc4IDgwLjE0OSwyMi43ODIgODAuMTM3LDIyLjc4NSBDNzguMzQ2LDIzLjgxMSA3Ni4zNDEsMjQuMzU0IDc0LjMzNiwyNC4zNTQgQzcxLjU4OCwyNC4zNTQgNjkuMDMzLDIzLjM0NyA2Ny4xNDIsMjEuNTE5IEw2Ni44NjQsMjEuMjQ5IEM2Ni4yNzcsMjAuNjM0IDY1Ljc3NCwxOS45NDcgNjUuMzY3LDE5LjIwMyBDNjUuMzYsMTkuMTkyIDY1LjM1NiwxOS4xNzkgNjUuMzU0LDE5LjE2NiBMNjUuMTYzLDE4LjgxOSBDNjUuMTU0LDE4LjgxMSA2NS4xNDYsMTguODAxIDY1LjE0LDE4Ljc5IEM2NC41MjUsMTcuNjY3IDYzLjM1NywxNi45OTcgNjIuMDE2LDE2Ljk5NyBMNjIuMDE2LDE2Ljk5NyBaIiBpZD0iRmlsbC03IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTQyLjQzNCw0OC44MDggTDQyLjQzNCw0OC44MDggQzM5LjkyNCw0OC44MDcgMzcuNzM3LDQ3LjU1IDM2LjU4Miw0NS40NDMgQzM0Ljc3MSw0Mi4xMzkgMzYuMTQ0LDM3LjgwOSAzOS42NDEsMzUuNzg5IEw1MS45MzIsMjguNjkxIEM1My4xMDMsMjguMDE1IDU0LjQxMywyNy42NTggNTUuNzIxLDI3LjY1OCBDNTguMjMxLDI3LjY1OCA2MC40MTgsMjguOTE2IDYxLjU3MywzMS4wMjMgQzYzLjM4NCwzNC4zMjcgNjIuMDEyLDM4LjY1NyA1OC41MTQsNDAuNjc3IEw0Ni4yMjMsNDcuNzc1IEM0NS4wNTMsNDguNDUgNDMuNzQyLDQ4LjgwOCA0Mi40MzQsNDguODA4IEw0Mi40MzQsNDguODA4IFogTTU1LjcyMSwyOC4xMjUgQzU0LjQ5NSwyOC4xMjUgNTMuMjY1LDI4LjQ2MSA1Mi4xNjYsMjkuMDk2IEwzOS44NzUsMzYuMTk0IEMzNi41OTYsMzguMDg3IDM1LjMwMiw0Mi4xMzYgMzYuOTkyLDQ1LjIxOCBDMzguMDYzLDQ3LjE3MyA0MC4wOTgsNDguMzQgNDIuNDM0LDQ4LjM0IEM0My42NjEsNDguMzQgNDQuODksNDguMDA1IDQ1Ljk5LDQ3LjM3IEw1OC4yODEsNDAuMjcyIEM2MS41NiwzOC4zNzkgNjIuODUzLDM0LjMzIDYxLjE2NCwzMS4yNDggQzYwLjA5MiwyOS4yOTMgNTguMDU4LDI4LjEyNSA1NS43MjEsMjguMTI1IEw1NS43MjEsMjguMTI1IFoiIGlkPSJGaWxsLTgiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTQ5LjU4OCwyLjQwNyBDMTQ5LjU4OCwyLjQwNyAxNTUuNzY4LDUuOTc1IDE1Ni4zMjUsNi4yOTcgTDE1Ni4zMjUsNy4xODQgQzE1Ni4zMjUsNy4zNiAxNTYuMzM4LDcuNTQ0IDE1Ni4zNjIsNy43MzMgQzE1Ni4zNzMsNy44MTQgMTU2LjM4Miw3Ljg5NCAxNTYuMzksNy45NzUgQzE1Ni41Myw5LjM5IDE1Ny4zNjMsMTAuOTczIDE1OC40OTUsMTEuOTc0IEwxNjUuODkxLDE4LjUxOSBDMTY2LjA2OCwxOC42NzUgMTY2LjI0OSwxOC44MTQgMTY2LjQzMiwxOC45MzQgQzE2OC4wMTEsMTkuOTc0IDE2OS4zODIsMTkuNCAxNjkuNDk0LDE3LjY1MiBDMTY5LjU0MywxNi44NjggMTY5LjU1MSwxNi4wNTcgMTY5LjUxNywxNS4yMjMgTDE2OS41MTQsMTUuMDYzIEwxNjkuNTE0LDEzLjkxMiBDMTcwLjc4LDE0LjY0MiAxOTUuNTAxLDI4LjkxNSAxOTUuNTAxLDI4LjkxNSBMMTk1LjUwMSw4Mi45MTUgQzE5NS41MDEsODQuMDA1IDE5NC43MzEsODQuNDQ1IDE5My43ODEsODMuODk3IEwxNTEuMzA4LDU5LjM3NCBDMTUwLjM1OCw1OC44MjYgMTQ5LjU4OCw1Ny40OTcgMTQ5LjU4OCw1Ni40MDggTDE0OS41ODgsMjIuMzc1IiBpZD0iRmlsbC05IiBmaWxsPSIjRkFGQUZBIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE5NC41NTMsODQuMjUgQzE5NC4yOTYsODQuMjUgMTk0LjAxMyw4NC4xNjUgMTkzLjcyMiw4My45OTcgTDE1MS4yNSw1OS40NzYgQzE1MC4yNjksNTguOTA5IDE0OS40NzEsNTcuNTMzIDE0OS40NzEsNTYuNDA4IEwxNDkuNDcxLDIyLjM3NSBMMTQ5LjcwNSwyMi4zNzUgTDE0OS43MDUsNTYuNDA4IEMxNDkuNzA1LDU3LjQ1OSAxNTAuNDUsNTguNzQ0IDE1MS4zNjYsNTkuMjc0IEwxOTMuODM5LDgzLjc5NSBDMTk0LjI2Myw4NC4wNCAxOTQuNjU1LDg0LjA4MyAxOTQuOTQyLDgzLjkxNyBDMTk1LjIyNyw4My43NTMgMTk1LjM4NCw4My4zOTcgMTk1LjM4NCw4Mi45MTUgTDE5NS4zODQsMjguOTgyIEMxOTQuMTAyLDI4LjI0MiAxNzIuMTA0LDE1LjU0MiAxNjkuNjMxLDE0LjExNCBMMTY5LjYzNCwxNS4yMiBDMTY5LjY2OCwxNi4wNTIgMTY5LjY2LDE2Ljg3NCAxNjkuNjEsMTcuNjU5IEMxNjkuNTU2LDE4LjUwMyAxNjkuMjE0LDE5LjEyMyAxNjguNjQ3LDE5LjQwNSBDMTY4LjAyOCwxOS43MTQgMTY3LjE5NywxOS41NzggMTY2LjM2NywxOS4wMzIgQzE2Ni4xODEsMTguOTA5IDE2NS45OTUsMTguNzY2IDE2NS44MTQsMTguNjA2IEwxNTguNDE3LDEyLjA2MiBDMTU3LjI1OSwxMS4wMzYgMTU2LjQxOCw5LjQzNyAxNTYuMjc0LDcuOTg2IEMxNTYuMjY2LDcuOTA3IDE1Ni4yNTcsNy44MjcgMTU2LjI0Nyw3Ljc0OCBDMTU2LjIyMSw3LjU1NSAxNTYuMjA5LDcuMzY1IDE1Ni4yMDksNy4xODQgTDE1Ni4yMDksNi4zNjQgQzE1NS4zNzUsNS44ODMgMTQ5LjUyOSwyLjUwOCAxNDkuNTI5LDIuNTA4IEwxNDkuNjQ2LDIuMzA2IEMxNDkuNjQ2LDIuMzA2IDE1NS44MjcsNS44NzQgMTU2LjM4NCw2LjE5NiBMMTU2LjQ0Miw2LjIzIEwxNTYuNDQyLDcuMTg0IEMxNTYuNDQyLDcuMzU1IDE1Ni40NTQsNy41MzUgMTU2LjQ3OCw3LjcxNyBDMTU2LjQ4OSw3LjggMTU2LjQ5OSw3Ljg4MiAxNTYuNTA3LDcuOTYzIEMxNTYuNjQ1LDkuMzU4IDE1Ny40NTUsMTAuODk4IDE1OC41NzIsMTEuODg2IEwxNjUuOTY5LDE4LjQzMSBDMTY2LjE0MiwxOC41ODQgMTY2LjMxOSwxOC43MiAxNjYuNDk2LDE4LjgzNyBDMTY3LjI1NCwxOS4zMzYgMTY4LDE5LjQ2NyAxNjguNTQzLDE5LjE5NiBDMTY5LjAzMywxOC45NTMgMTY5LjMyOSwxOC40MDEgMTY5LjM3NywxNy42NDUgQzE2OS40MjcsMTYuODY3IDE2OS40MzQsMTYuMDU0IDE2OS40MDEsMTUuMjI4IEwxNjkuMzk3LDE1LjA2NSBMMTY5LjM5NywxMy43MSBMMTY5LjU3MiwxMy44MSBDMTcwLjgzOSwxNC41NDEgMTk1LjU1OSwyOC44MTQgMTk1LjU1OSwyOC44MTQgTDE5NS42MTgsMjguODQ3IEwxOTUuNjE4LDgyLjkxNSBDMTk1LjYxOCw4My40ODQgMTk1LjQyLDgzLjkxMSAxOTUuMDU5LDg0LjExOSBDMTk0LjkwOCw4NC4yMDYgMTk0LjczNyw4NC4yNSAxOTQuNTUzLDg0LjI1IiBpZD0iRmlsbC0xMCIgZmlsbD0iIzYwN0Q4QiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNDUuNjg1LDU2LjE2MSBMMTY5LjgsNzAuMDgzIEwxNDMuODIyLDg1LjA4MSBMMTQyLjM2LDg0Ljc3NCBDMTM1LjgyNiw4Mi42MDQgMTI4LjczMiw4MS4wNDYgMTIxLjM0MSw4MC4xNTggQzExNi45NzYsNzkuNjM0IDExMi42NzgsODEuMjU0IDExMS43NDMsODMuNzc4IEMxMTEuNTA2LDg0LjQxNCAxMTEuNTAzLDg1LjA3MSAxMTEuNzMyLDg1LjcwNiBDMTEzLjI3LDg5Ljk3MyAxMTUuOTY4LDk0LjA2OSAxMTkuNzI3LDk3Ljg0MSBMMTIwLjI1OSw5OC42ODYgQzEyMC4yNiw5OC42ODUgOTQuMjgyLDExMy42ODMgOTQuMjgyLDExMy42ODMgTDcwLjE2Nyw5OS43NjEgTDE0NS42ODUsNTYuMTYxIiBpZD0iRmlsbC0xMSIgZmlsbD0iI0ZGRkZGRiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik05NC4yODIsMTEzLjgxOCBMOTQuMjIzLDExMy43ODUgTDY5LjkzMyw5OS43NjEgTDcwLjEwOCw5OS42NiBMMTQ1LjY4NSw1Ni4wMjYgTDE0NS43NDMsNTYuMDU5IEwxNzAuMDMzLDcwLjA4MyBMMTQzLjg0Miw4NS4yMDUgTDE0My43OTcsODUuMTk1IEMxNDMuNzcyLDg1LjE5IDE0Mi4zMzYsODQuODg4IDE0Mi4zMzYsODQuODg4IEMxMzUuNzg3LDgyLjcxNCAxMjguNzIzLDgxLjE2MyAxMjEuMzI3LDgwLjI3NCBDMTIwLjc4OCw4MC4yMDkgMTIwLjIzNiw4MC4xNzcgMTE5LjY4OSw4MC4xNzcgQzExNS45MzEsODAuMTc3IDExMi42MzUsODEuNzA4IDExMS44NTIsODMuODE5IEMxMTEuNjI0LDg0LjQzMiAxMTEuNjIxLDg1LjA1MyAxMTEuODQyLDg1LjY2NyBDMTEzLjM3Nyw4OS45MjUgMTE2LjA1OCw5My45OTMgMTE5LjgxLDk3Ljc1OCBMMTE5LjgyNiw5Ny43NzkgTDEyMC4zNTIsOTguNjE0IEMxMjAuMzU0LDk4LjYxNyAxMjAuMzU2LDk4LjYyIDEyMC4zNTgsOTguNjI0IEwxMjAuNDIyLDk4LjcyNiBMMTIwLjMxNyw5OC43ODcgQzEyMC4yNjQsOTguODE4IDk0LjU5OSwxMTMuNjM1IDk0LjM0LDExMy43ODUgTDk0LjI4MiwxMTMuODE4IEw5NC4yODIsMTEzLjgxOCBaIE03MC40MDEsOTkuNzYxIEw5NC4yODIsMTEzLjU0OSBMMTE5LjA4NCw5OS4yMjkgQzExOS42Myw5OC45MTQgMTE5LjkzLDk4Ljc0IDEyMC4xMDEsOTguNjU0IEwxMTkuNjM1LDk3LjkxNCBDMTE1Ljg2NCw5NC4xMjcgMTEzLjE2OCw5MC4wMzMgMTExLjYyMiw4NS43NDYgQzExMS4zODIsODUuMDc5IDExMS4zODYsODQuNDA0IDExMS42MzMsODMuNzM4IEMxMTIuNDQ4LDgxLjUzOSAxMTUuODM2LDc5Ljk0MyAxMTkuNjg5LDc5Ljk0MyBDMTIwLjI0Niw3OS45NDMgMTIwLjgwNiw3OS45NzYgMTIxLjM1NSw4MC4wNDIgQzEyOC43NjcsODAuOTMzIDEzNS44NDYsODIuNDg3IDE0Mi4zOTYsODQuNjYzIEMxNDMuMjMyLDg0LjgzOCAxNDMuNjExLDg0LjkxNyAxNDMuNzg2LDg0Ljk2NyBMMTY5LjU2Niw3MC4wODMgTDE0NS42ODUsNTYuMjk1IEw3MC40MDEsOTkuNzYxIEw3MC40MDEsOTkuNzYxIFoiIGlkPSJGaWxsLTEyIiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE2Ny4yMywxOC45NzkgTDE2Ny4yMyw2OS44NSBMMTM5LjkwOSw4NS42MjMgTDEzMy40NDgsNzEuNDU2IEMxMzIuNTM4LDY5LjQ2IDEzMC4wMiw2OS43MTggMTI3LjgyNCw3Mi4wMyBDMTI2Ljc2OSw3My4xNCAxMjUuOTMxLDc0LjU4NSAxMjUuNDk0LDc2LjA0OCBMMTE5LjAzNCw5Ny42NzYgTDkxLjcxMiwxMTMuNDUgTDkxLjcxMiw2Mi41NzkgTDE2Ny4yMywxOC45NzkiIGlkPSJGaWxsLTEzIiBmaWxsPSIjRkZGRkZGIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTkxLjcxMiwxMTMuNTY3IEM5MS42OTIsMTEzLjU2NyA5MS42NzIsMTEzLjU2MSA5MS42NTMsMTEzLjU1MSBDOTEuNjE4LDExMy41MyA5MS41OTUsMTEzLjQ5MiA5MS41OTUsMTEzLjQ1IEw5MS41OTUsNjIuNTc5IEM5MS41OTUsNjIuNTM3IDkxLjYxOCw2Mi40OTkgOTEuNjUzLDYyLjQ3OCBMMTY3LjE3MiwxOC44NzggQzE2Ny4yMDgsMTguODU3IDE2Ny4yNTIsMTguODU3IDE2Ny4yODgsMTguODc4IEMxNjcuMzI0LDE4Ljg5OSAxNjcuMzQ3LDE4LjkzNyAxNjcuMzQ3LDE4Ljk3OSBMMTY3LjM0Nyw2OS44NSBDMTY3LjM0Nyw2OS44OTEgMTY3LjMyNCw2OS45MyAxNjcuMjg4LDY5Ljk1IEwxMzkuOTY3LDg1LjcyNSBDMTM5LjkzOSw4NS43NDEgMTM5LjkwNSw4NS43NDUgMTM5Ljg3Myw4NS43MzUgQzEzOS44NDIsODUuNzI1IDEzOS44MTYsODUuNzAyIDEzOS44MDIsODUuNjcyIEwxMzMuMzQyLDcxLjUwNCBDMTMyLjk2Nyw3MC42ODIgMTMyLjI4LDcwLjIyOSAxMzEuNDA4LDcwLjIyOSBDMTMwLjMxOSw3MC4yMjkgMTI5LjA0NCw3MC45MTUgMTI3LjkwOCw3Mi4xMSBDMTI2Ljg3NCw3My4yIDEyNi4wMzQsNzQuNjQ3IDEyNS42MDYsNzYuMDgyIEwxMTkuMTQ2LDk3LjcwOSBDMTE5LjEzNyw5Ny43MzggMTE5LjExOCw5Ny43NjIgMTE5LjA5Miw5Ny43NzcgTDkxLjc3LDExMy41NTEgQzkxLjc1MiwxMTMuNTYxIDkxLjczMiwxMTMuNTY3IDkxLjcxMiwxMTMuNTY3IEw5MS43MTIsMTEzLjU2NyBaIE05MS44MjksNjIuNjQ3IEw5MS44MjksMTEzLjI0OCBMMTE4LjkzNSw5Ny41OTggTDEyNS4zODIsNzYuMDE1IEMxMjUuODI3LDc0LjUyNSAxMjYuNjY0LDczLjA4MSAxMjcuNzM5LDcxLjk1IEMxMjguOTE5LDcwLjcwOCAxMzAuMjU2LDY5Ljk5NiAxMzEuNDA4LDY5Ljk5NiBDMTMyLjM3Nyw2OS45OTYgMTMzLjEzOSw3MC40OTcgMTMzLjU1NCw3MS40MDcgTDEzOS45NjEsODUuNDU4IEwxNjcuMTEzLDY5Ljc4MiBMMTY3LjExMywxOS4xODEgTDkxLjgyOSw2Mi42NDcgTDkxLjgyOSw2Mi42NDcgWiIgaWQ9IkZpbGwtMTQiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTY4LjU0MywxOS4yMTMgTDE2OC41NDMsNzAuMDgzIEwxNDEuMjIxLDg1Ljg1NyBMMTM0Ljc2MSw3MS42ODkgQzEzMy44NTEsNjkuNjk0IDEzMS4zMzMsNjkuOTUxIDEyOS4xMzcsNzIuMjYzIEMxMjguMDgyLDczLjM3NCAxMjcuMjQ0LDc0LjgxOSAxMjYuODA3LDc2LjI4MiBMMTIwLjM0Niw5Ny45MDkgTDkzLjAyNSwxMTMuNjgzIEw5My4wMjUsNjIuODEzIEwxNjguNTQzLDE5LjIxMyIgaWQ9IkZpbGwtMTUiIGZpbGw9IiNGRkZGRkYiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNOTMuMDI1LDExMy44IEM5My4wMDUsMTEzLjggOTIuOTg0LDExMy43OTUgOTIuOTY2LDExMy43ODUgQzkyLjkzMSwxMTMuNzY0IDkyLjkwOCwxMTMuNzI1IDkyLjkwOCwxMTMuNjg0IEw5Mi45MDgsNjIuODEzIEM5Mi45MDgsNjIuNzcxIDkyLjkzMSw2Mi43MzMgOTIuOTY2LDYyLjcxMiBMMTY4LjQ4NCwxOS4xMTIgQzE2OC41MiwxOS4wOSAxNjguNTY1LDE5LjA5IDE2OC42MDEsMTkuMTEyIEMxNjguNjM3LDE5LjEzMiAxNjguNjYsMTkuMTcxIDE2OC42NiwxOS4yMTIgTDE2OC42Niw3MC4wODMgQzE2OC42Niw3MC4xMjUgMTY4LjYzNyw3MC4xNjQgMTY4LjYwMSw3MC4xODQgTDE0MS4yOCw4NS45NTggQzE0MS4yNTEsODUuOTc1IDE0MS4yMTcsODUuOTc5IDE0MS4xODYsODUuOTY4IEMxNDEuMTU0LDg1Ljk1OCAxNDEuMTI5LDg1LjkzNiAxNDEuMTE1LDg1LjkwNiBMMTM0LjY1NSw3MS43MzggQzEzNC4yOCw3MC45MTUgMTMzLjU5Myw3MC40NjMgMTMyLjcyLDcwLjQ2MyBDMTMxLjYzMiw3MC40NjMgMTMwLjM1Nyw3MS4xNDggMTI5LjIyMSw3Mi4zNDQgQzEyOC4xODYsNzMuNDMzIDEyNy4zNDcsNzQuODgxIDEyNi45MTksNzYuMzE1IEwxMjAuNDU4LDk3Ljk0MyBDMTIwLjQ1LDk3Ljk3MiAxMjAuNDMxLDk3Ljk5NiAxMjAuNDA1LDk4LjAxIEw5My4wODMsMTEzLjc4NSBDOTMuMDY1LDExMy43OTUgOTMuMDQ1LDExMy44IDkzLjAyNSwxMTMuOCBMOTMuMDI1LDExMy44IFogTTkzLjE0Miw2Mi44ODEgTDkzLjE0MiwxMTMuNDgxIEwxMjAuMjQ4LDk3LjgzMiBMMTI2LjY5NSw3Ni4yNDggQzEyNy4xNCw3NC43NTggMTI3Ljk3Nyw3My4zMTUgMTI5LjA1Miw3Mi4xODMgQzEzMC4yMzEsNzAuOTQyIDEzMS41NjgsNzAuMjI5IDEzMi43Miw3MC4yMjkgQzEzMy42ODksNzAuMjI5IDEzNC40NTIsNzAuNzMxIDEzNC44NjcsNzEuNjQxIEwxNDEuMjc0LDg1LjY5MiBMMTY4LjQyNiw3MC4wMTYgTDE2OC40MjYsMTkuNDE1IEw5My4xNDIsNjIuODgxIEw5My4xNDIsNjIuODgxIFoiIGlkPSJGaWxsLTE2IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE2OS44LDcwLjA4MyBMMTQyLjQ3OCw4NS44NTcgTDEzNi4wMTgsNzEuNjg5IEMxMzUuMTA4LDY5LjY5NCAxMzIuNTksNjkuOTUxIDEzMC4zOTMsNzIuMjYzIEMxMjkuMzM5LDczLjM3NCAxMjguNSw3NC44MTkgMTI4LjA2NCw3Ni4yODIgTDEyMS42MDMsOTcuOTA5IEw5NC4yODIsMTEzLjY4MyBMOTQuMjgyLDYyLjgxMyBMMTY5LjgsMTkuMjEzIEwxNjkuOCw3MC4wODMgWiIgaWQ9IkZpbGwtMTciIGZpbGw9IiNGQUZBRkEiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNOTQuMjgyLDExMy45MTcgQzk0LjI0MSwxMTMuOTE3IDk0LjIwMSwxMTMuOTA3IDk0LjE2NSwxMTMuODg2IEM5NC4wOTMsMTEzLjg0NSA5NC4wNDgsMTEzLjc2NyA5NC4wNDgsMTEzLjY4NCBMOTQuMDQ4LDYyLjgxMyBDOTQuMDQ4LDYyLjczIDk0LjA5Myw2Mi42NTIgOTQuMTY1LDYyLjYxMSBMMTY5LjY4MywxOS4wMSBDMTY5Ljc1NSwxOC45NjkgMTY5Ljg0NCwxOC45NjkgMTY5LjkxNywxOS4wMSBDMTY5Ljk4OSwxOS4wNTIgMTcwLjAzMywxOS4xMjkgMTcwLjAzMywxOS4yMTIgTDE3MC4wMzMsNzAuMDgzIEMxNzAuMDMzLDcwLjE2NiAxNjkuOTg5LDcwLjI0NCAxNjkuOTE3LDcwLjI4NSBMMTQyLjU5NSw4Ni4wNiBDMTQyLjUzOCw4Ni4wOTIgMTQyLjQ2OSw4Ni4xIDE0Mi40MDcsODYuMDggQzE0Mi4zNDQsODYuMDYgMTQyLjI5Myw4Ni4wMTQgMTQyLjI2Niw4NS45NTQgTDEzNS44MDUsNzEuNzg2IEMxMzUuNDQ1LDcwLjk5NyAxMzQuODEzLDcwLjU4IDEzMy45NzcsNzAuNTggQzEzMi45MjEsNzAuNTggMTMxLjY3Niw3MS4yNTIgMTMwLjU2Miw3Mi40MjQgQzEyOS41NCw3My41MDEgMTI4LjcxMSw3NC45MzEgMTI4LjI4Nyw3Ni4zNDggTDEyMS44MjcsOTcuOTc2IEMxMjEuODEsOTguMDM0IDEyMS43NzEsOTguMDgyIDEyMS43Miw5OC4xMTIgTDk0LjM5OCwxMTMuODg2IEM5NC4zNjIsMTEzLjkwNyA5NC4zMjIsMTEzLjkxNyA5NC4yODIsMTEzLjkxNyBMOTQuMjgyLDExMy45MTcgWiBNOTQuNTE1LDYyLjk0OCBMOTQuNTE1LDExMy4yNzkgTDEyMS40MDYsOTcuNzU0IEwxMjcuODQsNzYuMjE1IEMxMjguMjksNzQuNzA4IDEyOS4xMzcsNzMuMjQ3IDEzMC4yMjQsNzIuMTAzIEMxMzEuNDI1LDcwLjgzOCAxMzIuNzkzLDcwLjExMiAxMzMuOTc3LDcwLjExMiBDMTM0Ljk5NSw3MC4xMTIgMTM1Ljc5NSw3MC42MzggMTM2LjIzLDcxLjU5MiBMMTQyLjU4NCw4NS41MjYgTDE2OS41NjYsNjkuOTQ4IEwxNjkuNTY2LDE5LjYxNyBMOTQuNTE1LDYyLjk0OCBMOTQuNTE1LDYyLjk0OCBaIiBpZD0iRmlsbC0xOCIgZmlsbD0iIzYwN0Q4QiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xMDkuODk0LDkyLjk0MyBMMTA5Ljg5NCw5Mi45NDMgQzEwOC4xMiw5Mi45NDMgMTA2LjY1Myw5Mi4yMTggMTA1LjY1LDkwLjgyMyBDMTA1LjU4Myw5MC43MzEgMTA1LjU5Myw5MC42MSAxMDUuNjczLDkwLjUyOSBDMTA1Ljc1Myw5MC40NDggMTA1Ljg4LDkwLjQ0IDEwNS45NzQsOTAuNTA2IEMxMDYuNzU0LDkxLjA1MyAxMDcuNjc5LDkxLjMzMyAxMDguNzI0LDkxLjMzMyBDMTEwLjA0Nyw5MS4zMzMgMTExLjQ3OCw5MC44OTQgMTEyLjk4LDkwLjAyNyBDMTE4LjI5MSw4Ni45NiAxMjIuNjExLDc5LjUwOSAxMjIuNjExLDczLjQxNiBDMTIyLjYxMSw3MS40ODkgMTIyLjE2OSw2OS44NTYgMTIxLjMzMyw2OC42OTIgQzEyMS4yNjYsNjguNiAxMjEuMjc2LDY4LjQ3MyAxMjEuMzU2LDY4LjM5MiBDMTIxLjQzNiw2OC4zMTEgMTIxLjU2Myw2OC4yOTkgMTIxLjY1Niw2OC4zNjUgQzEyMy4zMjcsNjkuNTM3IDEyNC4yNDcsNzEuNzQ2IDEyNC4yNDcsNzQuNTg0IEMxMjQuMjQ3LDgwLjgyNiAxMTkuODIxLDg4LjQ0NyAxMTQuMzgyLDkxLjU4NyBDMTEyLjgwOCw5Mi40OTUgMTExLjI5OCw5Mi45NDMgMTA5Ljg5NCw5Mi45NDMgTDEwOS44OTQsOTIuOTQzIFogTTEwNi45MjUsOTEuNDAxIEMxMDcuNzM4LDkyLjA1MiAxMDguNzQ1LDkyLjI3OCAxMDkuODkzLDkyLjI3OCBMMTA5Ljg5NCw5Mi4yNzggQzExMS4yMTUsOTIuMjc4IDExMi42NDcsOTEuOTUxIDExNC4xNDgsOTEuMDg0IEMxMTkuNDU5LDg4LjAxNyAxMjMuNzgsODAuNjIxIDEyMy43OCw3NC41MjggQzEyMy43OCw3Mi41NDkgMTIzLjMxNyw3MC45MjkgMTIyLjQ1NCw2OS43NjcgQzEyMi44NjUsNzAuODAyIDEyMy4wNzksNzIuMDQyIDEyMy4wNzksNzMuNDAyIEMxMjMuMDc5LDc5LjY0NSAxMTguNjUzLDg3LjI4NSAxMTMuMjE0LDkwLjQyNSBDMTExLjY0LDkxLjMzNCAxMTAuMTMsOTEuNzQyIDEwOC43MjQsOTEuNzQyIEMxMDguMDgzLDkxLjc0MiAxMDcuNDgxLDkxLjU5MyAxMDYuOTI1LDkxLjQwMSBMMTA2LjkyNSw5MS40MDEgWiIgaWQ9IkZpbGwtMTkiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTEzLjA5Nyw5MC4yMyBDMTE4LjQ4MSw4Ny4xMjIgMTIyLjg0NSw3OS41OTQgMTIyLjg0NSw3My40MTYgQzEyMi44NDUsNzEuMzY1IDEyMi4zNjIsNjkuNzI0IDEyMS41MjIsNjguNTU2IEMxMTkuNzM4LDY3LjMwNCAxMTcuMTQ4LDY3LjM2MiAxMTQuMjY1LDY5LjAyNiBDMTA4Ljg4MSw3Mi4xMzQgMTA0LjUxNyw3OS42NjIgMTA0LjUxNyw4NS44NCBDMTA0LjUxNyw4Ny44OTEgMTA1LDg5LjUzMiAxMDUuODQsOTAuNyBDMTA3LjYyNCw5MS45NTIgMTEwLjIxNCw5MS44OTQgMTEzLjA5Nyw5MC4yMyIgaWQ9IkZpbGwtMjAiIGZpbGw9IiNGQUZBRkEiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTA4LjcyNCw5MS42MTQgTDEwOC43MjQsOTEuNjE0IEMxMDcuNTgyLDkxLjYxNCAxMDYuNTY2LDkxLjQwMSAxMDUuNzA1LDkwLjc5NyBDMTA1LjY4NCw5MC43ODMgMTA1LjY2NSw5MC44MTEgMTA1LjY1LDkwLjc5IEMxMDQuNzU2LDg5LjU0NiAxMDQuMjgzLDg3Ljg0MiAxMDQuMjgzLDg1LjgxNyBDMTA0LjI4Myw3OS41NzUgMTA4LjcwOSw3MS45NTMgMTE0LjE0OCw2OC44MTIgQzExNS43MjIsNjcuOTA0IDExNy4yMzIsNjcuNDQ5IDExOC42MzgsNjcuNDQ5IEMxMTkuNzgsNjcuNDQ5IDEyMC43OTYsNjcuNzU4IDEyMS42NTYsNjguMzYyIEMxMjEuNjc4LDY4LjM3NyAxMjEuNjk3LDY4LjM5NyAxMjEuNzEyLDY4LjQxOCBDMTIyLjYwNiw2OS42NjIgMTIzLjA3OSw3MS4zOSAxMjMuMDc5LDczLjQxNSBDMTIzLjA3OSw3OS42NTggMTE4LjY1Myw4Ny4xOTggMTEzLjIxNCw5MC4zMzggQzExMS42NCw5MS4yNDcgMTEwLjEzLDkxLjYxNCAxMDguNzI0LDkxLjYxNCBMMTA4LjcyNCw5MS42MTQgWiBNMTA2LjAwNiw5MC41MDUgQzEwNi43OCw5MS4wMzcgMTA3LjY5NCw5MS4yODEgMTA4LjcyNCw5MS4yODEgQzExMC4wNDcsOTEuMjgxIDExMS40NzgsOTAuODY4IDExMi45OCw5MC4wMDEgQzExOC4yOTEsODYuOTM1IDEyMi42MTEsNzkuNDk2IDEyMi42MTEsNzMuNDAzIEMxMjIuNjExLDcxLjQ5NCAxMjIuMTc3LDY5Ljg4IDEyMS4zNTYsNjguNzE4IEMxMjAuNTgyLDY4LjE4NSAxMTkuNjY4LDY3LjkxOSAxMTguNjM4LDY3LjkxOSBDMTE3LjMxNSw2Ny45MTkgMTE1Ljg4Myw2OC4zNiAxMTQuMzgyLDY5LjIyNyBDMTA5LjA3MSw3Mi4yOTMgMTA0Ljc1MSw3OS43MzMgMTA0Ljc1MSw4NS44MjYgQzEwNC43NTEsODcuNzM1IDEwNS4xODUsODkuMzQzIDEwNi4wMDYsOTAuNTA1IEwxMDYuMDA2LDkwLjUwNSBaIiBpZD0iRmlsbC0yMSIgZmlsbD0iIzYwN0Q4QiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNDkuMzE4LDcuMjYyIEwxMzkuMzM0LDE2LjE0IEwxNTUuMjI3LDI3LjE3MSBMMTYwLjgxNiwyMS4wNTkgTDE0OS4zMTgsNy4yNjIiIGlkPSJGaWxsLTIyIiBmaWxsPSIjRkFGQUZBIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE2OS42NzYsMTMuODQgTDE1OS45MjgsMTkuNDY3IEMxNTYuMjg2LDIxLjU3IDE1MC40LDIxLjU4IDE0Ni43ODEsMTkuNDkxIEMxNDMuMTYxLDE3LjQwMiAxNDMuMTgsMTQuMDAzIDE0Ni44MjIsMTEuOSBMMTU2LjMxNyw2LjI5MiBMMTQ5LjU4OCwyLjQwNyBMNjcuNzUyLDQ5LjQ3OCBMMTEzLjY3NSw3NS45OTIgTDExNi43NTYsNzQuMjEzIEMxMTcuMzg3LDczLjg0OCAxMTcuNjI1LDczLjMxNSAxMTcuMzc0LDcyLjgyMyBDMTE1LjAxNyw2OC4xOTEgMTE0Ljc4MSw2My4yNzcgMTE2LjY5MSw1OC41NjEgQzEyMi4zMjksNDQuNjQxIDE0MS4yLDMzLjc0NiAxNjUuMzA5LDMwLjQ5MSBDMTczLjQ3OCwyOS4zODggMTgxLjk4OSwyOS41MjQgMTkwLjAxMywzMC44ODUgQzE5MC44NjUsMzEuMDMgMTkxLjc4OSwzMC44OTMgMTkyLjQyLDMwLjUyOCBMMTk1LjUwMSwyOC43NSBMMTY5LjY3NiwxMy44NCIgaWQ9IkZpbGwtMjMiIGZpbGw9IiNGQUZBRkEiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTEzLjY3NSw3Ni40NTkgQzExMy41OTQsNzYuNDU5IDExMy41MTQsNzYuNDM4IDExMy40NDIsNzYuMzk3IEw2Ny41MTgsNDkuODgyIEM2Ny4zNzQsNDkuNzk5IDY3LjI4NCw0OS42NDUgNjcuMjg1LDQ5LjQ3OCBDNjcuMjg1LDQ5LjMxMSA2Ny4zNzQsNDkuMTU3IDY3LjUxOSw0OS4wNzMgTDE0OS4zNTUsMi4wMDIgQzE0OS40OTksMS45MTkgMTQ5LjY3NywxLjkxOSAxNDkuODIxLDIuMDAyIEwxNTYuNTUsNS44ODcgQzE1Ni43NzQsNi4wMTcgMTU2Ljg1LDYuMzAyIDE1Ni43MjIsNi41MjYgQzE1Ni41OTIsNi43NDkgMTU2LjMwNyw2LjgyNiAxNTYuMDgzLDYuNjk2IEwxNDkuNTg3LDIuOTQ2IEw2OC42ODcsNDkuNDc5IEwxMTMuNjc1LDc1LjQ1MiBMMTE2LjUyMyw3My44MDggQzExNi43MTUsNzMuNjk3IDExNy4xNDMsNzMuMzk5IDExNi45NTgsNzMuMDM1IEMxMTQuNTQyLDY4LjI4NyAxMTQuMyw2My4yMjEgMTE2LjI1OCw1OC4zODUgQzExOS4wNjQsNTEuNDU4IDEyNS4xNDMsNDUuMTQzIDEzMy44NCw0MC4xMjIgQzE0Mi40OTcsMzUuMTI0IDE1My4zNTgsMzEuNjMzIDE2NS4yNDcsMzAuMDI4IEMxNzMuNDQ1LDI4LjkyMSAxODIuMDM3LDI5LjA1OCAxOTAuMDkxLDMwLjQyNSBDMTkwLjgzLDMwLjU1IDE5MS42NTIsMzAuNDMyIDE5Mi4xODYsMzAuMTI0IEwxOTQuNTY3LDI4Ljc1IEwxNjkuNDQyLDE0LjI0NCBDMTY5LjIxOSwxNC4xMTUgMTY5LjE0MiwxMy44MjkgMTY5LjI3MSwxMy42MDYgQzE2OS40LDEzLjM4MiAxNjkuNjg1LDEzLjMwNiAxNjkuOTA5LDEzLjQzNSBMMTk1LjczNCwyOC4zNDUgQzE5NS44NzksMjguNDI4IDE5NS45NjgsMjguNTgzIDE5NS45NjgsMjguNzUgQzE5NS45NjgsMjguOTE2IDE5NS44NzksMjkuMDcxIDE5NS43MzQsMjkuMTU0IEwxOTIuNjUzLDMwLjkzMyBDMTkxLjkzMiwzMS4zNSAxOTAuODksMzEuNTA4IDE4OS45MzUsMzEuMzQ2IEMxODEuOTcyLDI5Ljk5NSAxNzMuNDc4LDI5Ljg2IDE2NS4zNzIsMzAuOTU0IEMxNTMuNjAyLDMyLjU0MyAxNDIuODYsMzUuOTkzIDEzNC4zMDcsNDAuOTMxIEMxMjUuNzkzLDQ1Ljg0NyAxMTkuODUxLDUyLjAwNCAxMTcuMTI0LDU4LjczNiBDMTE1LjI3LDYzLjMxNCAxMTUuNTAxLDY4LjExMiAxMTcuNzksNzIuNjExIEMxMTguMTYsNzMuMzM2IDExNy44NDUsNzQuMTI0IDExNi45OSw3NC42MTcgTDExMy45MDksNzYuMzk3IEMxMTMuODM2LDc2LjQzOCAxMTMuNzU2LDc2LjQ1OSAxMTMuNjc1LDc2LjQ1OSIgaWQ9IkZpbGwtMjQiIGZpbGw9IiM0NTVBNjQiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTUzLjMxNiwyMS4yNzkgQzE1MC45MDMsMjEuMjc5IDE0OC40OTUsMjAuNzUxIDE0Ni42NjQsMTkuNjkzIEMxNDQuODQ2LDE4LjY0NCAxNDMuODQ0LDE3LjIzMiAxNDMuODQ0LDE1LjcxOCBDMTQzLjg0NCwxNC4xOTEgMTQ0Ljg2LDEyLjc2MyAxNDYuNzA1LDExLjY5OCBMMTU2LjE5OCw2LjA5MSBDMTU2LjMwOSw2LjAyNSAxNTYuNDUyLDYuMDYyIDE1Ni41MTgsNi4xNzMgQzE1Ni41ODMsNi4yODQgMTU2LjU0Nyw2LjQyNyAxNTYuNDM2LDYuNDkzIEwxNDYuOTQsMTIuMTAyIEMxNDUuMjQ0LDEzLjA4MSAxNDQuMzEyLDE0LjM2NSAxNDQuMzEyLDE1LjcxOCBDMTQ0LjMxMiwxNy4wNTggMTQ1LjIzLDE4LjMyNiAxNDYuODk3LDE5LjI4OSBDMTUwLjQ0NiwyMS4zMzggMTU2LjI0LDIxLjMyNyAxNTkuODExLDE5LjI2NSBMMTY5LjU1OSwxMy42MzcgQzE2OS42NywxMy41NzMgMTY5LjgxMywxMy42MTEgMTY5Ljg3OCwxMy43MjMgQzE2OS45NDMsMTMuODM0IDE2OS45MDQsMTMuOTc3IDE2OS43OTMsMTQuMDQyIEwxNjAuMDQ1LDE5LjY3IEMxNTguMTg3LDIwLjc0MiAxNTUuNzQ5LDIxLjI3OSAxNTMuMzE2LDIxLjI3OSIgaWQ9IkZpbGwtMjUiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTEzLjY3NSw3NS45OTIgTDY3Ljc2Miw0OS40ODQiIGlkPSJGaWxsLTI2IiBmaWxsPSIjNDU1QTY0Ij48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTExMy42NzUsNzYuMzQyIEMxMTMuNjE1LDc2LjM0MiAxMTMuNTU1LDc2LjMyNyAxMTMuNSw3Ni4yOTUgTDY3LjU4Nyw0OS43ODcgQzY3LjQxOSw0OS42OSA2Ny4zNjIsNDkuNDc2IDY3LjQ1OSw0OS4zMDkgQzY3LjU1Niw0OS4xNDEgNjcuNzcsNDkuMDgzIDY3LjkzNyw0OS4xOCBMMTEzLjg1LDc1LjY4OCBDMTE0LjAxOCw3NS43ODUgMTE0LjA3NSw3NiAxMTMuOTc4LDc2LjE2NyBDMTEzLjkxNCw3Ni4yNzkgMTEzLjc5Niw3Ni4zNDIgMTEzLjY3NSw3Ni4zNDIiIGlkPSJGaWxsLTI3IiBmaWxsPSIjNDU1QTY0Ij48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTY3Ljc2Miw0OS40ODQgTDY3Ljc2MiwxMDMuNDg1IEM2Ny43NjIsMTA0LjU3NSA2OC41MzIsMTA1LjkwMyA2OS40ODIsMTA2LjQ1MiBMMTExLjk1NSwxMzAuOTczIEMxMTIuOTA1LDEzMS41MjIgMTEzLjY3NSwxMzEuMDgzIDExMy42NzUsMTI5Ljk5MyBMMTEzLjY3NSw3NS45OTIiIGlkPSJGaWxsLTI4IiBmaWxsPSIjRkFGQUZBIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTExMi43MjcsMTMxLjU2MSBDMTEyLjQzLDEzMS41NjEgMTEyLjEwNywxMzEuNDY2IDExMS43OCwxMzEuMjc2IEw2OS4zMDcsMTA2Ljc1NSBDNjguMjQ0LDEwNi4xNDIgNjcuNDEyLDEwNC43MDUgNjcuNDEyLDEwMy40ODUgTDY3LjQxMiw0OS40ODQgQzY3LjQxMiw0OS4yOSA2Ny41NjksNDkuMTM0IDY3Ljc2Miw0OS4xMzQgQzY3Ljk1Niw0OS4xMzQgNjguMTEzLDQ5LjI5IDY4LjExMyw0OS40ODQgTDY4LjExMywxMDMuNDg1IEM2OC4xMTMsMTA0LjQ0NSA2OC44MiwxMDUuNjY1IDY5LjY1NywxMDYuMTQ4IEwxMTIuMTMsMTMwLjY3IEMxMTIuNDc0LDEzMC44NjggMTEyLjc5MSwxMzAuOTEzIDExMywxMzAuNzkyIEMxMTMuMjA2LDEzMC42NzMgMTEzLjMyNSwxMzAuMzgxIDExMy4zMjUsMTI5Ljk5MyBMMTEzLjMyNSw3NS45OTIgQzExMy4zMjUsNzUuNzk4IDExMy40ODIsNzUuNjQxIDExMy42NzUsNzUuNjQxIEMxMTMuODY5LDc1LjY0MSAxMTQuMDI1LDc1Ljc5OCAxMTQuMDI1LDc1Ljk5MiBMMTE0LjAyNSwxMjkuOTkzIEMxMTQuMDI1LDEzMC42NDggMTEzLjc4NiwxMzEuMTQ3IDExMy4zNSwxMzEuMzk5IEMxMTMuMTYyLDEzMS41MDcgMTEyLjk1MiwxMzEuNTYxIDExMi43MjcsMTMxLjU2MSIgaWQ9IkZpbGwtMjkiIGZpbGw9IiM0NTVBNjQiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTEyLjg2LDQwLjUxMiBDMTEyLjg2LDQwLjUxMiAxMTIuODYsNDAuNTEyIDExMi44NTksNDAuNTEyIEMxMTAuNTQxLDQwLjUxMiAxMDguMzYsMzkuOTkgMTA2LjcxNywzOS4wNDEgQzEwNS4wMTIsMzguMDU3IDEwNC4wNzQsMzYuNzI2IDEwNC4wNzQsMzUuMjkyIEMxMDQuMDc0LDMzLjg0NyAxMDUuMDI2LDMyLjUwMSAxMDYuNzU0LDMxLjUwNCBMMTE4Ljc5NSwyNC41NTEgQzEyMC40NjMsMjMuNTg5IDEyMi42NjksMjMuMDU4IDEyNS4wMDcsMjMuMDU4IEMxMjcuMzI1LDIzLjA1OCAxMjkuNTA2LDIzLjU4MSAxMzEuMTUsMjQuNTMgQzEzMi44NTQsMjUuNTE0IDEzMy43OTMsMjYuODQ1IDEzMy43OTMsMjguMjc4IEMxMzMuNzkzLDI5LjcyNCAxMzIuODQxLDMxLjA2OSAxMzEuMTEzLDMyLjA2NyBMMTE5LjA3MSwzOS4wMTkgQzExNy40MDMsMzkuOTgyIDExNS4xOTcsNDAuNTEyIDExMi44Niw0MC41MTIgTDExMi44Niw0MC41MTIgWiBNMTI1LjAwNywyMy43NTkgQzEyMi43OSwyMy43NTkgMTIwLjcwOSwyNC4yNTYgMTE5LjE0NiwyNS4xNTggTDEwNy4xMDQsMzIuMTEgQzEwNS42MDIsMzIuOTc4IDEwNC43NzQsMzQuMTA4IDEwNC43NzQsMzUuMjkyIEMxMDQuNzc0LDM2LjQ2NSAxMDUuNTg5LDM3LjU4MSAxMDcuMDY3LDM4LjQzNCBDMTA4LjYwNSwzOS4zMjMgMTEwLjY2MywzOS44MTIgMTEyLjg1OSwzOS44MTIgTDExMi44NiwzOS44MTIgQzExNS4wNzYsMzkuODEyIDExNy4xNTgsMzkuMzE1IDExOC43MjEsMzguNDEzIEwxMzAuNzYyLDMxLjQ2IEMxMzIuMjY0LDMwLjU5MyAxMzMuMDkyLDI5LjQ2MyAxMzMuMDkyLDI4LjI3OCBDMTMzLjA5MiwyNy4xMDYgMTMyLjI3OCwyNS45OSAxMzAuOCwyNS4xMzYgQzEyOS4yNjEsMjQuMjQ4IDEyNy4yMDQsMjMuNzU5IDEyNS4wMDcsMjMuNzU5IEwxMjUuMDA3LDIzLjc1OSBaIiBpZD0iRmlsbC0zMCIgZmlsbD0iIzYwN0Q4QiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNjUuNjMsMTYuMjE5IEwxNTkuODk2LDE5LjUzIEMxNTYuNzI5LDIxLjM1OCAxNTEuNjEsMjEuMzY3IDE0OC40NjMsMTkuNTUgQzE0NS4zMTYsMTcuNzMzIDE0NS4zMzIsMTQuNzc4IDE0OC40OTksMTIuOTQ5IEwxNTQuMjMzLDkuNjM5IEwxNjUuNjMsMTYuMjE5IiBpZD0iRmlsbC0zMSIgZmlsbD0iI0ZBRkFGQSI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNTQuMjMzLDEwLjQ0OCBMMTY0LjIyOCwxNi4yMTkgTDE1OS41NDYsMTguOTIzIEMxNTguMTEyLDE5Ljc1IDE1Ni4xOTQsMjAuMjA2IDE1NC4xNDcsMjAuMjA2IEMxNTIuMTE4LDIwLjIwNiAxNTAuMjI0LDE5Ljc1NyAxNDguODE0LDE4Ljk0MyBDMTQ3LjUyNCwxOC4xOTkgMTQ2LjgxNCwxNy4yNDkgMTQ2LjgxNCwxNi4yNjkgQzE0Ni44MTQsMTUuMjc4IDE0Ny41MzcsMTQuMzE0IDE0OC44NSwxMy41NTYgTDE1NC4yMzMsMTAuNDQ4IE0xNTQuMjMzLDkuNjM5IEwxNDguNDk5LDEyLjk0OSBDMTQ1LjMzMiwxNC43NzggMTQ1LjMxNiwxNy43MzMgMTQ4LjQ2MywxOS41NSBDMTUwLjAzMSwyMC40NTUgMTUyLjA4NiwyMC45MDcgMTU0LjE0NywyMC45MDcgQzE1Ni4yMjQsMjAuOTA3IDE1OC4zMDYsMjAuNDQ3IDE1OS44OTYsMTkuNTMgTDE2NS42MywxNi4yMTkgTDE1NC4yMzMsOS42MzkiIGlkPSJGaWxsLTMyIiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE0NS40NDUsNzIuNjY3IEwxNDUuNDQ1LDcyLjY2NyBDMTQzLjY3Miw3Mi42NjcgMTQyLjIwNCw3MS44MTcgMTQxLjIwMiw3MC40MjIgQzE0MS4xMzUsNzAuMzMgMTQxLjE0NSw3MC4xNDcgMTQxLjIyNSw3MC4wNjYgQzE0MS4zMDUsNjkuOTg1IDE0MS40MzIsNjkuOTQ2IDE0MS41MjUsNzAuMDExIEMxNDIuMzA2LDcwLjU1OSAxNDMuMjMxLDcwLjgyMyAxNDQuMjc2LDcwLjgyMiBDMTQ1LjU5OCw3MC44MjIgMTQ3LjAzLDcwLjM3NiAxNDguNTMyLDY5LjUwOSBDMTUzLjg0Miw2Ni40NDMgMTU4LjE2Myw1OC45ODcgMTU4LjE2Myw1Mi44OTQgQzE1OC4xNjMsNTAuOTY3IDE1Ny43MjEsNDkuMzMyIDE1Ni44ODQsNDguMTY4IEMxNTYuODE4LDQ4LjA3NiAxNTYuODI4LDQ3Ljk0OCAxNTYuOTA4LDQ3Ljg2NyBDMTU2Ljk4OCw0Ny43ODYgMTU3LjExNCw0Ny43NzQgMTU3LjIwOCw0Ny44NCBDMTU4Ljg3OCw0OS4wMTIgMTU5Ljc5OCw1MS4yMiAxNTkuNzk4LDU0LjA1OSBDMTU5Ljc5OCw2MC4zMDEgMTU1LjM3Myw2OC4wNDYgMTQ5LjkzMyw3MS4xODYgQzE0OC4zNiw3Mi4wOTQgMTQ2Ljg1LDcyLjY2NyAxNDUuNDQ1LDcyLjY2NyBMMTQ1LjQ0NSw3Mi42NjcgWiBNMTQyLjQ3Niw3MSBDMTQzLjI5LDcxLjY1MSAxNDQuMjk2LDcyLjAwMiAxNDUuNDQ1LDcyLjAwMiBDMTQ2Ljc2Nyw3Mi4wMDIgMTQ4LjE5OCw3MS41NSAxNDkuNyw3MC42ODIgQzE1NS4wMSw2Ny42MTcgMTU5LjMzMSw2MC4xNTkgMTU5LjMzMSw1NC4wNjUgQzE1OS4zMzEsNTIuMDg1IDE1OC44NjgsNTAuNDM1IDE1OC4wMDYsNDkuMjcyIEMxNTguNDE3LDUwLjMwNyAxNTguNjMsNTEuNTMyIDE1OC42Myw1Mi44OTIgQzE1OC42Myw1OS4xMzQgMTU0LjIwNSw2Ni43NjcgMTQ4Ljc2NSw2OS45MDcgQzE0Ny4xOTIsNzAuODE2IDE0NS42ODEsNzEuMjgzIDE0NC4yNzYsNzEuMjgzIEMxNDMuNjM0LDcxLjI4MyAxNDMuMDMzLDcxLjE5MiAxNDIuNDc2LDcxIEwxNDIuNDc2LDcxIFoiIGlkPSJGaWxsLTMzIiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE0OC42NDgsNjkuNzA0IEMxNTQuMDMyLDY2LjU5NiAxNTguMzk2LDU5LjA2OCAxNTguMzk2LDUyLjg5MSBDMTU4LjM5Niw1MC44MzkgMTU3LjkxMyw0OS4xOTggMTU3LjA3NCw0OC4wMyBDMTU1LjI4OSw0Ni43NzggMTUyLjY5OSw0Ni44MzYgMTQ5LjgxNiw0OC41MDEgQzE0NC40MzMsNTEuNjA5IDE0MC4wNjgsNTkuMTM3IDE0MC4wNjgsNjUuMzE0IEMxNDAuMDY4LDY3LjM2NSAxNDAuNTUyLDY5LjAwNiAxNDEuMzkxLDcwLjE3NCBDMTQzLjE3Niw3MS40MjcgMTQ1Ljc2NSw3MS4zNjkgMTQ4LjY0OCw2OS43MDQiIGlkPSJGaWxsLTM0IiBmaWxsPSIjRkFGQUZBIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE0NC4yNzYsNzEuMjc2IEwxNDQuMjc2LDcxLjI3NiBDMTQzLjEzMyw3MS4yNzYgMTQyLjExOCw3MC45NjkgMTQxLjI1Nyw3MC4zNjUgQzE0MS4yMzYsNzAuMzUxIDE0MS4yMTcsNzAuMzMyIDE0MS4yMDIsNzAuMzExIEMxNDAuMzA3LDY5LjA2NyAxMzkuODM1LDY3LjMzOSAxMzkuODM1LDY1LjMxNCBDMTM5LjgzNSw1OS4wNzMgMTQ0LjI2LDUxLjQzOSAxNDkuNyw0OC4yOTggQzE1MS4yNzMsNDcuMzkgMTUyLjc4NCw0Ni45MjkgMTU0LjE4OSw0Ni45MjkgQzE1NS4zMzIsNDYuOTI5IDE1Ni4zNDcsNDcuMjM2IDE1Ny4yMDgsNDcuODM5IEMxNTcuMjI5LDQ3Ljg1NCAxNTcuMjQ4LDQ3Ljg3MyAxNTcuMjYzLDQ3Ljg5NCBDMTU4LjE1Nyw0OS4xMzggMTU4LjYzLDUwLjg2NSAxNTguNjMsNTIuODkxIEMxNTguNjMsNTkuMTMyIDE1NC4yMDUsNjYuNzY2IDE0OC43NjUsNjkuOTA3IEMxNDcuMTkyLDcwLjgxNSAxNDUuNjgxLDcxLjI3NiAxNDQuMjc2LDcxLjI3NiBMMTQ0LjI3Niw3MS4yNzYgWiBNMTQxLjU1OCw3MC4xMDQgQzE0Mi4zMzEsNzAuNjM3IDE0My4yNDUsNzEuMDA1IDE0NC4yNzYsNzEuMDA1IEMxNDUuNTk4LDcxLjAwNSAxNDcuMDMsNzAuNDY3IDE0OC41MzIsNjkuNiBDMTUzLjg0Miw2Ni41MzQgMTU4LjE2Myw1OS4wMzMgMTU4LjE2Myw1Mi45MzkgQzE1OC4xNjMsNTEuMDMxIDE1Ny43MjksNDkuMzg1IDE1Ni45MDcsNDguMjIzIEMxNTYuMTMzLDQ3LjY5MSAxNTUuMjE5LDQ3LjQwOSAxNTQuMTg5LDQ3LjQwOSBDMTUyLjg2Nyw0Ny40MDkgMTUxLjQzNSw0Ny44NDIgMTQ5LjkzMyw0OC43MDkgQzE0NC42MjMsNTEuNzc1IDE0MC4zMDIsNTkuMjczIDE0MC4zMDIsNjUuMzY2IEMxNDAuMzAyLDY3LjI3NiAxNDAuNzM2LDY4Ljk0MiAxNDEuNTU4LDcwLjEwNCBMMTQxLjU1OCw3MC4xMDQgWiIgaWQ9IkZpbGwtMzUiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTUwLjcyLDY1LjM2MSBMMTUwLjM1Nyw2NS4wNjYgQzE1MS4xNDcsNjQuMDkyIDE1MS44NjksNjMuMDQgMTUyLjUwNSw2MS45MzggQzE1My4zMTMsNjAuNTM5IDE1My45NzgsNTkuMDY3IDE1NC40ODIsNTcuNTYzIEwxNTQuOTI1LDU3LjcxMiBDMTU0LjQxMiw1OS4yNDUgMTUzLjczMyw2MC43NDUgMTUyLjkxLDYyLjE3MiBDMTUyLjI2Miw2My4yOTUgMTUxLjUyNSw2NC4zNjggMTUwLjcyLDY1LjM2MSIgaWQ9IkZpbGwtMzYiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTE1LjkxNyw4NC41MTQgTDExNS41NTQsODQuMjIgQzExNi4zNDQsODMuMjQ1IDExNy4wNjYsODIuMTk0IDExNy43MDIsODEuMDkyIEMxMTguNTEsNzkuNjkyIDExOS4xNzUsNzguMjIgMTE5LjY3OCw3Ni43MTcgTDEyMC4xMjEsNzYuODY1IEMxMTkuNjA4LDc4LjM5OCAxMTguOTMsNzkuODk5IDExOC4xMDYsODEuMzI2IEMxMTcuNDU4LDgyLjQ0OCAxMTYuNzIyLDgzLjUyMSAxMTUuOTE3LDg0LjUxNCIgaWQ9IkZpbGwtMzciIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTE0LDEzMC40NzYgTDExNCwxMzAuMDA4IEwxMTQsNzYuMDUyIEwxMTQsNzUuNTg0IEwxMTQsNzYuMDUyIEwxMTQsMTMwLjAwOCBMMTE0LDEzMC40NzYiIGlkPSJGaWxsLTM4IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgICA8ZyBpZD0iSW1wb3J0ZWQtTGF5ZXJzLUNvcHkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDYyLjAwMDAwMCwgMC4wMDAwMDApIiBza2V0Y2g6dHlwZT0iTVNTaGFwZUdyb3VwIj4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTkuODIyLDM3LjQ3NCBDMTkuODM5LDM3LjMzOSAxOS43NDcsMzcuMTk0IDE5LjU1NSwzNy4wODIgQzE5LjIyOCwzNi44OTQgMTguNzI5LDM2Ljg3MiAxOC40NDYsMzcuMDM3IEwxMi40MzQsNDAuNTA4IEMxMi4zMDMsNDAuNTg0IDEyLjI0LDQwLjY4NiAxMi4yNDMsNDAuNzkzIEMxMi4yNDUsNDAuOTI1IDEyLjI0NSw0MS4yNTQgMTIuMjQ1LDQxLjM3MSBMMTIuMjQ1LDQxLjQxNCBMMTIuMjM4LDQxLjU0MiBDOC4xNDgsNDMuODg3IDUuNjQ3LDQ1LjMyMSA1LjY0Nyw0NS4zMjEgQzUuNjQ2LDQ1LjMyMSAzLjU3LDQ2LjM2NyAyLjg2LDUwLjUxMyBDMi44Niw1MC41MTMgMS45NDgsNTcuNDc0IDEuOTYyLDcwLjI1OCBDMS45NzcsODIuODI4IDIuNTY4LDg3LjMyOCAzLjEyOSw5MS42MDkgQzMuMzQ5LDkzLjI5MyA2LjEzLDkzLjczNCA2LjEzLDkzLjczNCBDNi40NjEsOTMuNzc0IDYuODI4LDkzLjcwNyA3LjIxLDkzLjQ4NiBMODIuNDgzLDQ5LjkzNSBDODQuMjkxLDQ4Ljg2NiA4NS4xNSw0Ni4yMTYgODUuNTM5LDQzLjY1MSBDODYuNzUyLDM1LjY2MSA4Ny4yMTQsMTAuNjczIDg1LjI2NCwzLjc3MyBDODUuMDY4LDMuMDggODQuNzU0LDIuNjkgODQuMzk2LDIuNDkxIEw4Mi4zMSwxLjcwMSBDODEuNTgzLDEuNzI5IDgwLjg5NCwyLjE2OCA4MC43NzYsMi4yMzYgQzgwLjYzNiwyLjMxNyA0MS44MDcsMjQuNTg1IDIwLjAzMiwzNy4wNzIgTDE5LjgyMiwzNy40NzQiIGlkPSJGaWxsLTEiIGZpbGw9IiNGRkZGRkYiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNODIuMzExLDEuNzAxIEw4NC4zOTYsMi40OTEgQzg0Ljc1NCwyLjY5IDg1LjA2OCwzLjA4IDg1LjI2NCwzLjc3MyBDODcuMjEzLDEwLjY3MyA4Ni43NTEsMzUuNjYgODUuNTM5LDQzLjY1MSBDODUuMTQ5LDQ2LjIxNiA4NC4yOSw0OC44NjYgODIuNDgzLDQ5LjkzNSBMNy4yMSw5My40ODYgQzYuODk3LDkzLjY2NyA2LjU5NSw5My43NDQgNi4zMTQsOTMuNzQ0IEw2LjEzMSw5My43MzMgQzYuMTMxLDkzLjczNCAzLjM0OSw5My4yOTMgMy4xMjgsOTEuNjA5IEMyLjU2OCw4Ny4zMjcgMS45NzcsODIuODI4IDEuOTYzLDcwLjI1OCBDMS45NDgsNTcuNDc0IDIuODYsNTAuNTEzIDIuODYsNTAuNTEzIEMzLjU3LDQ2LjM2NyA1LjY0Nyw0NS4zMjEgNS42NDcsNDUuMzIxIEM1LjY0Nyw0NS4zMjEgOC4xNDgsNDMuODg3IDEyLjIzOCw0MS41NDIgTDEyLjI0NSw0MS40MTQgTDEyLjI0NSw0MS4zNzEgQzEyLjI0NSw0MS4yNTQgMTIuMjQ1LDQwLjkyNSAxMi4yNDMsNDAuNzkzIEMxMi4yNCw0MC42ODYgMTIuMzAyLDQwLjU4MyAxMi40MzQsNDAuNTA4IEwxOC40NDYsMzcuMDM2IEMxOC41NzQsMzYuOTYyIDE4Ljc0NiwzNi45MjYgMTguOTI3LDM2LjkyNiBDMTkuMTQ1LDM2LjkyNiAxOS4zNzYsMzYuOTc5IDE5LjU1NCwzNy4wODIgQzE5Ljc0NywzNy4xOTQgMTkuODM5LDM3LjM0IDE5LjgyMiwzNy40NzQgTDIwLjAzMywzNy4wNzIgQzQxLjgwNiwyNC41ODUgODAuNjM2LDIuMzE4IDgwLjc3NywyLjIzNiBDODAuODk0LDIuMTY4IDgxLjU4MywxLjcyOSA4Mi4zMTEsMS43MDEgTTgyLjMxMSwwLjcwNCBMODIuMjcyLDAuNzA1IEM4MS42NTQsMC43MjggODAuOTg5LDAuOTQ5IDgwLjI5OCwxLjM2MSBMODAuMjc3LDEuMzczIEM4MC4xMjksMS40NTggNTkuNzY4LDEzLjEzNSAxOS43NTgsMzYuMDc5IEMxOS41LDM1Ljk4MSAxOS4yMTQsMzUuOTI5IDE4LjkyNywzNS45MjkgQzE4LjU2MiwzNS45MjkgMTguMjIzLDM2LjAxMyAxNy45NDcsMzYuMTczIEwxMS45MzUsMzkuNjQ0IEMxMS40OTMsMzkuODk5IDExLjIzNiw0MC4zMzQgMTEuMjQ2LDQwLjgxIEwxMS4yNDcsNDAuOTYgTDUuMTY3LDQ0LjQ0NyBDNC43OTQsNDQuNjQ2IDIuNjI1LDQ1Ljk3OCAxLjg3Nyw1MC4zNDUgTDEuODcxLDUwLjM4NCBDMS44NjIsNTAuNDU0IDAuOTUxLDU3LjU1NyAwLjk2NSw3MC4yNTkgQzAuOTc5LDgyLjg3OSAxLjU2OCw4Ny4zNzUgMi4xMzcsOTEuNzI0IEwyLjEzOSw5MS43MzkgQzIuNDQ3LDk0LjA5NCA1LjYxNCw5NC42NjIgNS45NzUsOTQuNzE5IEw2LjAwOSw5NC43MjMgQzYuMTEsOTQuNzM2IDYuMjEzLDk0Ljc0MiA2LjMxNCw5NC43NDIgQzYuNzksOTQuNzQyIDcuMjYsOTQuNjEgNy43MSw5NC4zNSBMODIuOTgzLDUwLjc5OCBDODQuNzk0LDQ5LjcyNyA4NS45ODIsNDcuMzc1IDg2LjUyNSw0My44MDEgQzg3LjcxMSwzNS45ODcgODguMjU5LDEwLjcwNSA4Ni4yMjQsMy41MDIgQzg1Ljk3MSwyLjYwOSA4NS41MiwxLjk3NSA4NC44ODEsMS42MiBMODQuNzQ5LDEuNTU4IEw4Mi42NjQsMC43NjkgQzgyLjU1MSwwLjcyNSA4Mi40MzEsMC43MDQgODIuMzExLDAuNzA0IiBpZD0iRmlsbC0yIiBmaWxsPSIjNDU1QTY0Ij48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTY2LjI2NywxMS41NjUgTDY3Ljc2MiwxMS45OTkgTDExLjQyMyw0NC4zMjUiIGlkPSJGaWxsLTMiIGZpbGw9IiNGRkZGRkYiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTIuMjAyLDkwLjU0NSBDMTIuMDI5LDkwLjU0NSAxMS44NjIsOTAuNDU1IDExLjc2OSw5MC4yOTUgQzExLjYzMiw5MC4wNTcgMTEuNzEzLDg5Ljc1MiAxMS45NTIsODkuNjE0IEwzMC4zODksNzguOTY5IEMzMC42MjgsNzguODMxIDMwLjkzMyw3OC45MTMgMzEuMDcxLDc5LjE1MiBDMzEuMjA4LDc5LjM5IDMxLjEyNyw3OS42OTYgMzAuODg4LDc5LjgzMyBMMTIuNDUxLDkwLjQ3OCBMMTIuMjAyLDkwLjU0NSIgaWQ9IkZpbGwtNCIgZmlsbD0iIzYwN0Q4QiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xMy43NjQsNDIuNjU0IEwxMy42NTYsNDIuNTkyIEwxMy43MDIsNDIuNDIxIEwxOC44MzcsMzkuNDU3IEwxOS4wMDcsMzkuNTAyIEwxOC45NjIsMzkuNjczIEwxMy44MjcsNDIuNjM3IEwxMy43NjQsNDIuNjU0IiBpZD0iRmlsbC01IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTguNTIsOTAuMzc1IEw4LjUyLDQ2LjQyMSBMOC41ODMsNDYuMzg1IEw3NS44NCw3LjU1NCBMNzUuODQsNTEuNTA4IEw3NS43NzgsNTEuNTQ0IEw4LjUyLDkwLjM3NSBMOC41Miw5MC4zNzUgWiBNOC43Nyw0Ni41NjQgTDguNzcsODkuOTQ0IEw3NS41OTEsNTEuMzY1IEw3NS41OTEsNy45ODUgTDguNzcsNDYuNTY0IEw4Ljc3LDQ2LjU2NCBaIiBpZD0iRmlsbC02IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTI0Ljk4Niw4My4xODIgQzI0Ljc1Niw4My4zMzEgMjQuMzc0LDgzLjU2NiAyNC4xMzcsODMuNzA1IEwxMi42MzIsOTAuNDA2IEMxMi4zOTUsOTAuNTQ1IDEyLjQyNiw5MC42NTggMTIuNyw5MC42NTggTDEzLjI2NSw5MC42NTggQzEzLjU0LDkwLjY1OCAxMy45NTgsOTAuNTQ1IDE0LjE5NSw5MC40MDYgTDI1LjcsODMuNzA1IEMyNS45MzcsODMuNTY2IDI2LjEyOCw4My40NTIgMjYuMTI1LDgzLjQ0OSBDMjYuMTIyLDgzLjQ0NyAyNi4xMTksODMuMjIgMjYuMTE5LDgyLjk0NiBDMjYuMTE5LDgyLjY3MiAyNS45MzEsODIuNTY5IDI1LjcwMSw4Mi43MTkgTDI0Ljk4Niw4My4xODIiIGlkPSJGaWxsLTciIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTMuMjY2LDkwLjc4MiBMMTIuNyw5MC43ODIgQzEyLjUsOTAuNzgyIDEyLjM4NCw5MC43MjYgMTIuMzU0LDkwLjYxNiBDMTIuMzI0LDkwLjUwNiAxMi4zOTcsOTAuMzk5IDEyLjU2OSw5MC4yOTkgTDI0LjA3NCw4My41OTcgQzI0LjMxLDgzLjQ1OSAyNC42ODksODMuMjI2IDI0LjkxOCw4My4wNzggTDI1LjYzMyw4Mi42MTQgQzI1LjcyMyw4Mi41NTUgMjUuODEzLDgyLjUyNSAyNS44OTksODIuNTI1IEMyNi4wNzEsODIuNTI1IDI2LjI0NCw4Mi42NTUgMjYuMjQ0LDgyLjk0NiBDMjYuMjQ0LDgzLjE2IDI2LjI0NSw4My4zMDkgMjYuMjQ3LDgzLjM4MyBMMjYuMjUzLDgzLjM4NyBMMjYuMjQ5LDgzLjQ1NiBDMjYuMjQ2LDgzLjUzMSAyNi4yNDYsODMuNTMxIDI1Ljc2Myw4My44MTIgTDE0LjI1OCw5MC41MTQgQzE0LDkwLjY2NSAxMy41NjQsOTAuNzgyIDEzLjI2Niw5MC43ODIgTDEzLjI2Niw5MC43ODIgWiBNMTIuNjY2LDkwLjUzMiBMMTIuNyw5MC41MzMgTDEzLjI2Niw5MC41MzMgQzEzLjUxOCw5MC41MzMgMTMuOTE1LDkwLjQyNSAxNC4xMzIsOTAuMjk5IEwyNS42MzcsODMuNTk3IEMyNS44MDUsODMuNDk5IDI1LjkzMSw4My40MjQgMjUuOTk4LDgzLjM4MyBDMjUuOTk0LDgzLjI5OSAyNS45OTQsODMuMTY1IDI1Ljk5NCw4Mi45NDYgTDI1Ljg5OSw4Mi43NzUgTDI1Ljc2OCw4Mi44MjQgTDI1LjA1NCw4My4yODcgQzI0LjgyMiw4My40MzcgMjQuNDM4LDgzLjY3MyAyNC4yLDgzLjgxMiBMMTIuNjk1LDkwLjUxNCBMMTIuNjY2LDkwLjUzMiBMMTIuNjY2LDkwLjUzMiBaIiBpZD0iRmlsbC04IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTEzLjI2Niw4OS44NzEgTDEyLjcsODkuODcxIEMxMi41LDg5Ljg3MSAxMi4zODQsODkuODE1IDEyLjM1NCw4OS43MDUgQzEyLjMyNCw4OS41OTUgMTIuMzk3LDg5LjQ4OCAxMi41NjksODkuMzg4IEwyNC4wNzQsODIuNjg2IEMyNC4zMzIsODIuNTM1IDI0Ljc2OCw4Mi40MTggMjUuMDY3LDgyLjQxOCBMMjUuNjMyLDgyLjQxOCBDMjUuODMyLDgyLjQxOCAyNS45NDgsODIuNDc0IDI1Ljk3OCw4Mi41ODQgQzI2LjAwOCw4Mi42OTQgMjUuOTM1LDgyLjgwMSAyNS43NjMsODIuOTAxIEwxNC4yNTgsODkuNjAzIEMxNCw4OS43NTQgMTMuNTY0LDg5Ljg3MSAxMy4yNjYsODkuODcxIEwxMy4yNjYsODkuODcxIFogTTEyLjY2Niw4OS42MjEgTDEyLjcsODkuNjIyIEwxMy4yNjYsODkuNjIyIEMxMy41MTgsODkuNjIyIDEzLjkxNSw4OS41MTUgMTQuMTMyLDg5LjM4OCBMMjUuNjM3LDgyLjY4NiBMMjUuNjY3LDgyLjY2OCBMMjUuNjMyLDgyLjY2NyBMMjUuMDY3LDgyLjY2NyBDMjQuODE1LDgyLjY2NyAyNC40MTgsODIuNzc1IDI0LjIsODIuOTAxIEwxMi42OTUsODkuNjAzIEwxMi42NjYsODkuNjIxIEwxMi42NjYsODkuNjIxIFoiIGlkPSJGaWxsLTkiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTIuMzcsOTAuODAxIEwxMi4zNyw4OS41NTQgTDEyLjM3LDkwLjgwMSIgaWQ9IkZpbGwtMTAiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNNi4xMyw5My45MDEgQzUuMzc5LDkzLjgwOCA0LjgxNiw5My4xNjQgNC42OTEsOTIuNTI1IEMzLjg2LDg4LjI4NyAzLjU0LDgzLjc0MyAzLjUyNiw3MS4xNzMgQzMuNTExLDU4LjM4OSA0LjQyMyw1MS40MjggNC40MjMsNTEuNDI4IEM1LjEzNCw0Ny4yODIgNy4yMSw0Ni4yMzYgNy4yMSw0Ni4yMzYgQzcuMjEsNDYuMjM2IDgxLjY2NywzLjI1IDgyLjA2OSwzLjAxNyBDODIuMjkyLDIuODg4IDg0LjU1NiwxLjQzMyA4NS4yNjQsMy45NCBDODcuMjE0LDEwLjg0IDg2Ljc1MiwzNS44MjcgODUuNTM5LDQzLjgxOCBDODUuMTUsNDYuMzgzIDg0LjI5MSw0OS4wMzMgODIuNDgzLDUwLjEwMSBMNy4yMSw5My42NTMgQzYuODI4LDkzLjg3NCA2LjQ2MSw5My45NDEgNi4xMyw5My45MDEgQzYuMTMsOTMuOTAxIDMuMzQ5LDkzLjQ2IDMuMTI5LDkxLjc3NiBDMi41NjgsODcuNDk1IDEuOTc3LDgyLjk5NSAxLjk2Miw3MC40MjUgQzEuOTQ4LDU3LjY0MSAyLjg2LDUwLjY4IDIuODYsNTAuNjggQzMuNTcsNDYuNTM0IDUuNjQ3LDQ1LjQ4OSA1LjY0Nyw0NS40ODkgQzUuNjQ2LDQ1LjQ4OSA4LjA2NSw0NC4wOTIgMTIuMjQ1LDQxLjY3OSBMMTMuMTE2LDQxLjU2IEwxOS43MTUsMzcuNzMgTDE5Ljc2MSwzNy4yNjkgTDYuMTMsOTMuOTAxIiBpZD0iRmlsbC0xMSIgZmlsbD0iI0ZBRkFGQSI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik02LjMxNyw5NC4xNjEgTDYuMTAyLDk0LjE0OCBMNi4xMDEsOTQuMTQ4IEw1Ljg1Nyw5NC4xMDEgQzUuMTM4LDkzLjk0NSAzLjA4NSw5My4zNjUgMi44ODEsOTEuODA5IEMyLjMxMyw4Ny40NjkgMS43MjcsODIuOTk2IDEuNzEzLDcwLjQyNSBDMS42OTksNTcuNzcxIDIuNjA0LDUwLjcxOCAyLjYxMyw1MC42NDggQzMuMzM4LDQ2LjQxNyA1LjQ0NSw0NS4zMSA1LjUzNSw0NS4yNjYgTDEyLjE2Myw0MS40MzkgTDEzLjAzMyw0MS4zMiBMMTkuNDc5LDM3LjU3OCBMMTkuNTEzLDM3LjI0NCBDMTkuNTI2LDM3LjEwNyAxOS42NDcsMzcuMDA4IDE5Ljc4NiwzNy4wMjEgQzE5LjkyMiwzNy4wMzQgMjAuMDIzLDM3LjE1NiAyMC4wMDksMzcuMjkzIEwxOS45NSwzNy44ODIgTDEzLjE5OCw0MS44MDEgTDEyLjMyOCw0MS45MTkgTDUuNzcyLDQ1LjcwNCBDNS43NDEsNDUuNzIgMy43ODIsNDYuNzcyIDMuMTA2LDUwLjcyMiBDMy4wOTksNTAuNzgyIDIuMTk4LDU3LjgwOCAyLjIxMiw3MC40MjQgQzIuMjI2LDgyLjk2MyAyLjgwOSw4Ny40MiAzLjM3Myw5MS43MjkgQzMuNDY0LDkyLjQyIDQuMDYyLDkyLjg4MyA0LjY4Miw5My4xODEgQzQuNTY2LDkyLjk4NCA0LjQ4Niw5Mi43NzYgNC40NDYsOTIuNTcyIEMzLjY2NSw4OC41ODggMy4yOTEsODQuMzcgMy4yNzYsNzEuMTczIEMzLjI2Miw1OC41MiA0LjE2Nyw1MS40NjYgNC4xNzYsNTEuMzk2IEM0LjkwMSw0Ny4xNjUgNy4wMDgsNDYuMDU5IDcuMDk4LDQ2LjAxNCBDNy4wOTQsNDYuMDE1IDgxLjU0MiwzLjAzNCA4MS45NDQsMi44MDIgTDgxLjk3MiwyLjc4NSBDODIuODc2LDIuMjQ3IDgzLjY5MiwyLjA5NyA4NC4zMzIsMi4zNTIgQzg0Ljg4NywyLjU3MyA4NS4yODEsMy4wODUgODUuNTA0LDMuODcyIEM4Ny41MTgsMTEgODYuOTY0LDM2LjA5MSA4NS43ODUsNDMuODU1IEM4NS4yNzgsNDcuMTk2IDg0LjIxLDQ5LjM3IDgyLjYxLDUwLjMxNyBMNy4zMzUsOTMuODY5IEM2Ljk5OSw5NC4wNjMgNi42NTgsOTQuMTYxIDYuMzE3LDk0LjE2MSBMNi4zMTcsOTQuMTYxIFogTTYuMTcsOTMuNjU0IEM2LjQ2Myw5My42OSA2Ljc3NCw5My42MTcgNy4wODUsOTMuNDM3IEw4Mi4zNTgsNDkuODg2IEM4NC4xODEsNDguODA4IDg0Ljk2LDQ1Ljk3MSA4NS4yOTIsNDMuNzggQzg2LjQ2NiwzNi4wNDkgODcuMDIzLDExLjA4NSA4NS4wMjQsNC4wMDggQzg0Ljg0NiwzLjM3NyA4NC41NTEsMi45NzYgODQuMTQ4LDIuODE2IEM4My42NjQsMi42MjMgODIuOTgyLDIuNzY0IDgyLjIyNywzLjIxMyBMODIuMTkzLDMuMjM0IEM4MS43OTEsMy40NjYgNy4zMzUsNDYuNDUyIDcuMzM1LDQ2LjQ1MiBDNy4zMDQsNDYuNDY5IDUuMzQ2LDQ3LjUyMSA0LjY2OSw1MS40NzEgQzQuNjYyLDUxLjUzIDMuNzYxLDU4LjU1NiAzLjc3NSw3MS4xNzMgQzMuNzksODQuMzI4IDQuMTYxLDg4LjUyNCA0LjkzNiw5Mi40NzYgQzUuMDI2LDkyLjkzNyA1LjQxMiw5My40NTkgNS45NzMsOTMuNjE1IEM2LjA4Nyw5My42NCA2LjE1OCw5My42NTIgNi4xNjksOTMuNjU0IEw2LjE3LDkzLjY1NCBMNi4xNyw5My42NTQgWiIgaWQ9IkZpbGwtMTIiIGZpbGw9IiM0NTVBNjQiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNNy4zMTcsNjguOTgyIEM3LjgwNiw2OC43MDEgOC4yMDIsNjguOTI2IDguMjAyLDY5LjQ4NyBDOC4yMDIsNzAuMDQ3IDcuODA2LDcwLjczIDcuMzE3LDcxLjAxMiBDNi44MjksNzEuMjk0IDYuNDMzLDcxLjA2OSA2LjQzMyw3MC41MDggQzYuNDMzLDY5Ljk0OCA2LjgyOSw2OS4yNjUgNy4zMTcsNjguOTgyIiBpZD0iRmlsbC0xMyIgZmlsbD0iI0ZGRkZGRiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik02LjkyLDcxLjEzMyBDNi42MzEsNzEuMTMzIDYuNDMzLDcwLjkwNSA2LjQzMyw3MC41MDggQzYuNDMzLDY5Ljk0OCA2LjgyOSw2OS4yNjUgNy4zMTcsNjguOTgyIEM3LjQ2LDY4LjkgNy41OTUsNjguODYxIDcuNzE0LDY4Ljg2MSBDOC4wMDMsNjguODYxIDguMjAyLDY5LjA5IDguMjAyLDY5LjQ4NyBDOC4yMDIsNzAuMDQ3IDcuODA2LDcwLjczIDcuMzE3LDcxLjAxMiBDNy4xNzQsNzEuMDk0IDcuMDM5LDcxLjEzMyA2LjkyLDcxLjEzMyBNNy43MTQsNjguNjc0IEM3LjU1Nyw2OC42NzQgNy4zOTIsNjguNzIzIDcuMjI0LDY4LjgyMSBDNi42NzYsNjkuMTM4IDYuMjQ2LDY5Ljg3OSA2LjI0Niw3MC41MDggQzYuMjQ2LDcwLjk5NCA2LjUxNyw3MS4zMiA2LjkyLDcxLjMyIEM3LjA3OCw3MS4zMiA3LjI0Myw3MS4yNzEgNy40MTEsNzEuMTc0IEM3Ljk1OSw3MC44NTcgOC4zODksNzAuMTE3IDguMzg5LDY5LjQ4NyBDOC4zODksNjkuMDAxIDguMTE3LDY4LjY3NCA3LjcxNCw2OC42NzQiIGlkPSJGaWxsLTE0IiBmaWxsPSIjODA5N0EyIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTYuOTIsNzAuOTQ3IEM2LjY0OSw3MC45NDcgNi42MjEsNzAuNjQgNi42MjEsNzAuNTA4IEM2LjYyMSw3MC4wMTcgNi45ODIsNjkuMzkyIDcuNDExLDY5LjE0NSBDNy41MjEsNjkuMDgyIDcuNjI1LDY5LjA0OSA3LjcxNCw2OS4wNDkgQzcuOTg2LDY5LjA0OSA4LjAxNSw2OS4zNTUgOC4wMTUsNjkuNDg3IEM4LjAxNSw2OS45NzggNy42NTIsNzAuNjAzIDcuMjI0LDcwLjg1MSBDNy4xMTUsNzAuOTE0IDcuMDEsNzAuOTQ3IDYuOTIsNzAuOTQ3IE03LjcxNCw2OC44NjEgQzcuNTk1LDY4Ljg2MSA3LjQ2LDY4LjkgNy4zMTcsNjguOTgyIEM2LjgyOSw2OS4yNjUgNi40MzMsNjkuOTQ4IDYuNDMzLDcwLjUwOCBDNi40MzMsNzAuOTA1IDYuNjMxLDcxLjEzMyA2LjkyLDcxLjEzMyBDNy4wMzksNzEuMTMzIDcuMTc0LDcxLjA5NCA3LjMxNyw3MS4wMTIgQzcuODA2LDcwLjczIDguMjAyLDcwLjA0NyA4LjIwMiw2OS40ODcgQzguMjAyLDY5LjA5IDguMDAzLDY4Ljg2MSA3LjcxNCw2OC44NjEiIGlkPSJGaWxsLTE1IiBmaWxsPSIjODA5N0EyIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTcuNDQ0LDg1LjM1IEM3LjcwOCw4NS4xOTggNy45MjEsODUuMzE5IDcuOTIxLDg1LjYyMiBDNy45MjEsODUuOTI1IDcuNzA4LDg2LjI5MiA3LjQ0NCw4Ni40NDQgQzcuMTgxLDg2LjU5NyA2Ljk2Nyw4Ni40NzUgNi45NjcsODYuMTczIEM2Ljk2Nyw4NS44NzEgNy4xODEsODUuNTAyIDcuNDQ0LDg1LjM1IiBpZD0iRmlsbC0xNiIgZmlsbD0iI0ZGRkZGRiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik03LjIzLDg2LjUxIEM3LjA3NCw4Ni41MSA2Ljk2Nyw4Ni4zODcgNi45NjcsODYuMTczIEM2Ljk2Nyw4NS44NzEgNy4xODEsODUuNTAyIDcuNDQ0LDg1LjM1IEM3LjUyMSw4NS4zMDUgNy41OTQsODUuMjg0IDcuNjU4LDg1LjI4NCBDNy44MTQsODUuMjg0IDcuOTIxLDg1LjQwOCA3LjkyMSw4NS42MjIgQzcuOTIxLDg1LjkyNSA3LjcwOCw4Ni4yOTIgNy40NDQsODYuNDQ0IEM3LjM2Nyw4Ni40ODkgNy4yOTQsODYuNTEgNy4yMyw4Ni41MSBNNy42NTgsODUuMDk4IEM3LjU1OCw4NS4wOTggNy40NTUsODUuMTI3IDcuMzUxLDg1LjE4OCBDNy4wMzEsODUuMzczIDYuNzgxLDg1LjgwNiA2Ljc4MSw4Ni4xNzMgQzYuNzgxLDg2LjQ4MiA2Ljk2Niw4Ni42OTcgNy4yMyw4Ni42OTcgQzcuMzMsODYuNjk3IDcuNDMzLDg2LjY2NiA3LjUzOCw4Ni42MDcgQzcuODU4LDg2LjQyMiA4LjEwOCw4NS45ODkgOC4xMDgsODUuNjIyIEM4LjEwOCw4NS4zMTMgNy45MjMsODUuMDk4IDcuNjU4LDg1LjA5OCIgaWQ9IkZpbGwtMTciIGZpbGw9IiM4MDk3QTIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNNy4yMyw4Ni4zMjIgTDcuMTU0LDg2LjE3MyBDNy4xNTQsODUuOTM4IDcuMzMzLDg1LjYyOSA3LjUzOCw4NS41MTIgTDcuNjU4LDg1LjQ3MSBMNy43MzQsODUuNjIyIEM3LjczNCw4NS44NTYgNy41NTUsODYuMTY0IDcuMzUxLDg2LjI4MiBMNy4yMyw4Ni4zMjIgTTcuNjU4LDg1LjI4NCBDNy41OTQsODUuMjg0IDcuNTIxLDg1LjMwNSA3LjQ0NCw4NS4zNSBDNy4xODEsODUuNTAyIDYuOTY3LDg1Ljg3MSA2Ljk2Nyw4Ni4xNzMgQzYuOTY3LDg2LjM4NyA3LjA3NCw4Ni41MSA3LjIzLDg2LjUxIEM3LjI5NCw4Ni41MSA3LjM2Nyw4Ni40ODkgNy40NDQsODYuNDQ0IEM3LjcwOCw4Ni4yOTIgNy45MjEsODUuOTI1IDcuOTIxLDg1LjYyMiBDNy45MjEsODUuNDA4IDcuODE0LDg1LjI4NCA3LjY1OCw4NS4yODQiIGlkPSJGaWxsLTE4IiBmaWxsPSIjODA5N0EyIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTc3LjI3OCw3Ljc2OSBMNzcuMjc4LDUxLjQzNiBMMTAuMjA4LDkwLjE2IEwxMC4yMDgsNDYuNDkzIEw3Ny4yNzgsNy43NjkiIGlkPSJGaWxsLTE5IiBmaWxsPSIjNDU1QTY0Ij48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTEwLjA4Myw5MC4zNzUgTDEwLjA4Myw0Ni40MjEgTDEwLjE0Niw0Ni4zODUgTDc3LjQwMyw3LjU1NCBMNzcuNDAzLDUxLjUwOCBMNzcuMzQxLDUxLjU0NCBMMTAuMDgzLDkwLjM3NSBMMTAuMDgzLDkwLjM3NSBaIE0xMC4zMzMsNDYuNTY0IEwxMC4zMzMsODkuOTQ0IEw3Ny4xNTQsNTEuMzY1IEw3Ny4xNTQsNy45ODUgTDEwLjMzMyw0Ni41NjQgTDEwLjMzMyw0Ni41NjQgWiIgaWQ9IkZpbGwtMjAiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgIDwvZz4KICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xMjUuNzM3LDg4LjY0NyBMMTE4LjA5OCw5MS45ODEgTDExOC4wOTgsODQgTDEwNi42MzksODguNzEzIEwxMDYuNjM5LDk2Ljk4MiBMOTksMTAwLjMxNSBMMTEyLjM2OSwxMDMuOTYxIEwxMjUuNzM3LDg4LjY0NyIgaWQ9IkltcG9ydGVkLUxheWVycy1Db3B5LTIiIGZpbGw9IiM0NTVBNjQiIHNrZXRjaDp0eXBlPSJNU1NoYXBlR3JvdXAiPjwvcGF0aD4KICAgICAgICAgICAgPC9nPgogICAgICAgIDwvZz4KICAgIDwvZz4KPC9zdmc+';
2418
+ function RotateInstructions() {
2419
+ this.loadIcon_();
2420
+ var overlay = document.createElement('div');
2421
+ var s = overlay.style;
2422
+ s.position = 'fixed';
2423
+ s.top = 0;
2424
+ s.right = 0;
2425
+ s.bottom = 0;
2426
+ s.left = 0;
2427
+ s.backgroundColor = 'gray';
2428
+ s.fontFamily = 'sans-serif';
2429
+ s.zIndex = 1000000;
2430
+ var img = document.createElement('img');
2431
+ img.src = this.icon;
2432
+ var s = img.style;
2433
+ s.marginLeft = '25%';
2434
+ s.marginTop = '25%';
2435
+ s.width = '50%';
2436
+ overlay.appendChild(img);
2437
+ var text = document.createElement('div');
2438
+ var s = text.style;
2439
+ s.textAlign = 'center';
2440
+ s.fontSize = '16px';
2441
+ s.lineHeight = '24px';
2442
+ s.margin = '24px 25%';
2443
+ s.width = '50%';
2444
+ text.innerHTML = 'Place your phone into your Cardboard viewer.';
2445
+ overlay.appendChild(text);
2446
+ var snackbar = document.createElement('div');
2447
+ var s = snackbar.style;
2448
+ s.backgroundColor = '#CFD8DC';
2449
+ s.position = 'fixed';
2450
+ s.bottom = 0;
2451
+ s.width = '100%';
2452
+ s.height = '48px';
2453
+ s.padding = '14px 24px';
2454
+ s.boxSizing = 'border-box';
2455
+ s.color = '#656A6B';
2456
+ overlay.appendChild(snackbar);
2457
+ var snackbarText = document.createElement('div');
2458
+ snackbarText.style.float = 'left';
2459
+ snackbarText.innerHTML = 'No Cardboard viewer?';
2460
+ var snackbarButton = document.createElement('a');
2461
+ snackbarButton.href = 'https://www.google.com/get/cardboard/get-cardboard/';
2462
+ snackbarButton.innerHTML = 'get one';
2463
+ snackbarButton.target = '_blank';
2464
+ var s = snackbarButton.style;
2465
+ s.float = 'right';
2466
+ s.fontWeight = 600;
2467
+ s.textTransform = 'uppercase';
2468
+ s.borderLeft = '1px solid gray';
2469
+ s.paddingLeft = '24px';
2470
+ s.textDecoration = 'none';
2471
+ s.color = '#656A6B';
2472
+ snackbar.appendChild(snackbarText);
2473
+ snackbar.appendChild(snackbarButton);
2474
+ this.overlay = overlay;
2475
+ this.text = text;
2476
+ this.hide();
2477
+ }
2478
+ RotateInstructions.prototype.show = function (parent) {
2479
+ if (!parent && !this.overlay.parentElement) {
2480
+ document.body.appendChild(this.overlay);
2481
+ } else if (parent) {
2482
+ if (this.overlay.parentElement && this.overlay.parentElement != parent) this.overlay.parentElement.removeChild(this.overlay);
2483
+ parent.appendChild(this.overlay);
2484
+ }
2485
+ this.overlay.style.display = 'block';
2486
+ var img = this.overlay.querySelector('img');
2487
+ var s = img.style;
2488
+ if (isLandscapeMode()) {
2489
+ s.width = '20%';
2490
+ s.marginLeft = '40%';
2491
+ s.marginTop = '3%';
2492
+ } else {
2493
+ s.width = '50%';
2494
+ s.marginLeft = '25%';
2495
+ s.marginTop = '25%';
2496
+ }
2497
+ };
2498
+ RotateInstructions.prototype.hide = function () {
2499
+ this.overlay.style.display = 'none';
2500
+ };
2501
+ RotateInstructions.prototype.showTemporarily = function (ms, parent) {
2502
+ this.show(parent);
2503
+ this.timer = setTimeout(this.hide.bind(this), ms);
2504
+ };
2505
+ RotateInstructions.prototype.disableShowTemporarily = function () {
2506
+ clearTimeout(this.timer);
2507
+ };
2508
+ RotateInstructions.prototype.update = function () {
2509
+ this.disableShowTemporarily();
2510
+ if (!isLandscapeMode() && isMobile()) {
2511
+ this.show();
2512
+ } else {
2513
+ this.hide();
2514
+ }
2515
+ };
2516
+ RotateInstructions.prototype.loadIcon_ = function () {
2517
+ this.icon = base64('image/svg+xml', rotateInstructionsAsset);
2518
+ };
2519
+ var DEFAULT_VIEWER = 'CardboardV1';
2520
+ var VIEWER_KEY = 'WEBVR_CARDBOARD_VIEWER';
2521
+ var CLASS_NAME = 'webvr-polyfill-viewer-selector';
2522
+ function ViewerSelector(defaultViewer) {
2523
+ try {
2524
+ this.selectedKey = localStorage.getItem(VIEWER_KEY);
2525
+ } catch (error) {
2526
+ console.error('Failed to load viewer profile: %s', error);
2527
+ }
2528
+ if (!this.selectedKey) {
2529
+ this.selectedKey = defaultViewer || DEFAULT_VIEWER;
2530
+ }
2531
+ this.dialog = this.createDialog_(DeviceInfo.Viewers);
2532
+ this.root = null;
2533
+ this.onChangeCallbacks_ = [];
2534
+ }
2535
+ ViewerSelector.prototype.show = function (root) {
2536
+ this.root = root;
2537
+ root.appendChild(this.dialog);
2538
+ var selected = this.dialog.querySelector('#' + this.selectedKey);
2539
+ selected.checked = true;
2540
+ this.dialog.style.display = 'block';
2541
+ };
2542
+ ViewerSelector.prototype.hide = function () {
2543
+ if (this.root && this.root.contains(this.dialog)) {
2544
+ this.root.removeChild(this.dialog);
2545
+ }
2546
+ this.dialog.style.display = 'none';
2547
+ };
2548
+ ViewerSelector.prototype.getCurrentViewer = function () {
2549
+ return DeviceInfo.Viewers[this.selectedKey];
2550
+ };
2551
+ ViewerSelector.prototype.getSelectedKey_ = function () {
2552
+ var input = this.dialog.querySelector('input[name=field]:checked');
2553
+ if (input) {
2554
+ return input.id;
2555
+ }
2556
+ return null;
2557
+ };
2558
+ ViewerSelector.prototype.onChange = function (cb) {
2559
+ this.onChangeCallbacks_.push(cb);
2560
+ };
2561
+ ViewerSelector.prototype.fireOnChange_ = function (viewer) {
2562
+ for (var i = 0; i < this.onChangeCallbacks_.length; i++) {
2563
+ this.onChangeCallbacks_[i](viewer);
2564
+ }
2565
+ };
2566
+ ViewerSelector.prototype.onSave_ = function () {
2567
+ this.selectedKey = this.getSelectedKey_();
2568
+ if (!this.selectedKey || !DeviceInfo.Viewers[this.selectedKey]) {
2569
+ console.error('ViewerSelector.onSave_: this should never happen!');
2570
+ return;
2571
+ }
2572
+ this.fireOnChange_(DeviceInfo.Viewers[this.selectedKey]);
2573
+ try {
2574
+ localStorage.setItem(VIEWER_KEY, this.selectedKey);
2575
+ } catch (error) {
2576
+ console.error('Failed to save viewer profile: %s', error);
2577
+ }
2578
+ this.hide();
2579
+ };
2580
+ ViewerSelector.prototype.createDialog_ = function (options) {
2581
+ var container = document.createElement('div');
2582
+ container.classList.add(CLASS_NAME);
2583
+ container.style.display = 'none';
2584
+ var overlay = document.createElement('div');
2585
+ var s = overlay.style;
2586
+ s.position = 'fixed';
2587
+ s.left = 0;
2588
+ s.top = 0;
2589
+ s.width = '100%';
2590
+ s.height = '100%';
2591
+ s.background = 'rgba(0, 0, 0, 0.3)';
2592
+ overlay.addEventListener('click', this.hide.bind(this));
2593
+ var width = 280;
2594
+ var dialog = document.createElement('div');
2595
+ var s = dialog.style;
2596
+ s.boxSizing = 'border-box';
2597
+ s.position = 'fixed';
2598
+ s.top = '24px';
2599
+ s.left = '50%';
2600
+ s.marginLeft = -width / 2 + 'px';
2601
+ s.width = width + 'px';
2602
+ s.padding = '24px';
2603
+ s.overflow = 'hidden';
2604
+ s.background = '#fafafa';
2605
+ s.fontFamily = "'Roboto', sans-serif";
2606
+ s.boxShadow = '0px 5px 20px #666';
2607
+ dialog.appendChild(this.createH1_('Select your viewer'));
2608
+ for (var id in options) {
2609
+ dialog.appendChild(this.createChoice_(id, options[id].label));
2610
+ }
2611
+ dialog.appendChild(this.createButton_('Save', this.onSave_.bind(this)));
2612
+ container.appendChild(overlay);
2613
+ container.appendChild(dialog);
2614
+ return container;
2615
+ };
2616
+ ViewerSelector.prototype.createH1_ = function (name) {
2617
+ var h1 = document.createElement('h1');
2618
+ var s = h1.style;
2619
+ s.color = 'black';
2620
+ s.fontSize = '20px';
2621
+ s.fontWeight = 'bold';
2622
+ s.marginTop = 0;
2623
+ s.marginBottom = '24px';
2624
+ h1.innerHTML = name;
2625
+ return h1;
2626
+ };
2627
+ ViewerSelector.prototype.createChoice_ = function (id, name) {
2628
+ var div = document.createElement('div');
2629
+ div.style.marginTop = '8px';
2630
+ div.style.color = 'black';
2631
+ var input = document.createElement('input');
2632
+ input.style.fontSize = '30px';
2633
+ input.setAttribute('id', id);
2634
+ input.setAttribute('type', 'radio');
2635
+ input.setAttribute('value', id);
2636
+ input.setAttribute('name', 'field');
2637
+ var label = document.createElement('label');
2638
+ label.style.marginLeft = '4px';
2639
+ label.setAttribute('for', id);
2640
+ label.innerHTML = name;
2641
+ div.appendChild(input);
2642
+ div.appendChild(label);
2643
+ return div;
2644
+ };
2645
+ ViewerSelector.prototype.createButton_ = function (label, onclick) {
2646
+ var button = document.createElement('button');
2647
+ button.innerHTML = label;
2648
+ var s = button.style;
2649
+ s.float = 'right';
2650
+ s.textTransform = 'uppercase';
2651
+ s.color = '#1094f7';
2652
+ s.fontSize = '14px';
2653
+ s.letterSpacing = 0;
2654
+ s.border = 0;
2655
+ s.background = 'none';
2656
+ s.marginTop = '16px';
2657
+ button.addEventListener('click', onclick);
2658
+ return button;
2659
+ };
2660
+ var commonjsGlobal$$1 = typeof window !== 'undefined' ? window : typeof commonjsGlobal !== 'undefined' ? commonjsGlobal : typeof self !== 'undefined' ? self : {};
2661
+ function unwrapExports$$1 (x) {
2662
+ return x && x.__esModule ? x['default'] : x;
2663
+ }
2664
+ function createCommonjsModule$$1(fn, module) {
2665
+ return module = { exports: {} }, fn(module, module.exports), module.exports;
2666
+ }
2667
+ var NoSleep = createCommonjsModule$$1(function (module, exports) {
2668
+ (function webpackUniversalModuleDefinition(root, factory) {
2669
+ module.exports = factory();
2670
+ })(commonjsGlobal$$1, function() {
2671
+ return (function(modules) {
2672
+ var installedModules = {};
2673
+ function __webpack_require__(moduleId) {
2674
+ if(installedModules[moduleId]) {
2675
+ return installedModules[moduleId].exports;
2676
+ }
2677
+ var module = installedModules[moduleId] = {
2678
+ i: moduleId,
2679
+ l: false,
2680
+ exports: {}
2681
+ };
2682
+ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
2683
+ module.l = true;
2684
+ return module.exports;
2685
+ }
2686
+ __webpack_require__.m = modules;
2687
+ __webpack_require__.c = installedModules;
2688
+ __webpack_require__.d = function(exports, name, getter) {
2689
+ if(!__webpack_require__.o(exports, name)) {
2690
+ Object.defineProperty(exports, name, {
2691
+ configurable: false,
2692
+ enumerable: true,
2693
+ get: getter
2694
+ });
2695
+ }
2696
+ };
2697
+ __webpack_require__.n = function(module) {
2698
+ var getter = module && module.__esModule ?
2699
+ function getDefault() { return module['default']; } :
2700
+ function getModuleExports() { return module; };
2701
+ __webpack_require__.d(getter, 'a', getter);
2702
+ return getter;
2703
+ };
2704
+ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
2705
+ __webpack_require__.p = "";
2706
+ return __webpack_require__(__webpack_require__.s = 0);
2707
+ })
2708
+ ([
2709
+ (function(module, exports, __webpack_require__) {
2710
+ var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
2711
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
2712
+ var mediaFile = __webpack_require__(1);
2713
+ var oldIOS = typeof navigator !== 'undefined' && parseFloat(('' + (/CPU.*OS ([0-9_]{3,4})[0-9_]{0,1}|(CPU like).*AppleWebKit.*Mobile/i.exec(navigator.userAgent) || [0, ''])[1]).replace('undefined', '3_2').replace('_', '.').replace('_', '')) < 10 && !window.MSStream;
2714
+ var NoSleep = function () {
2715
+ function NoSleep() {
2716
+ _classCallCheck(this, NoSleep);
2717
+ if (oldIOS) {
2718
+ this.noSleepTimer = null;
2719
+ } else {
2720
+ this.noSleepVideo = document.createElement('video');
2721
+ this.noSleepVideo.setAttribute('playsinline', '');
2722
+ this.noSleepVideo.setAttribute('src', mediaFile);
2723
+ this.noSleepVideo.addEventListener('timeupdate', function (e) {
2724
+ if (this.noSleepVideo.currentTime > 0.5) {
2725
+ this.noSleepVideo.currentTime = Math.random();
2726
+ }
2727
+ }.bind(this));
2728
+ }
2729
+ }
2730
+ _createClass(NoSleep, [{
2731
+ key: 'enable',
2732
+ value: function enable() {
2733
+ if (oldIOS) {
2734
+ this.disable();
2735
+ this.noSleepTimer = window.setInterval(function () {
2736
+ window.location.href = '/';
2737
+ window.setTimeout(window.stop, 0);
2738
+ }, 15000);
2739
+ } else {
2740
+ this.noSleepVideo.play();
2741
+ }
2742
+ }
2743
+ }, {
2744
+ key: 'disable',
2745
+ value: function disable() {
2746
+ if (oldIOS) {
2747
+ if (this.noSleepTimer) {
2748
+ window.clearInterval(this.noSleepTimer);
2749
+ this.noSleepTimer = null;
2750
+ }
2751
+ } else {
2752
+ this.noSleepVideo.pause();
2753
+ }
2754
+ }
2755
+ }]);
2756
+ return NoSleep;
2757
+ }();
2758
+ module.exports = NoSleep;
2759
+ }),
2760
+ (function(module, exports, __webpack_require__) {
2761
+ module.exports = 'data:video/mp4;base64,AAAAIGZ0eXBtcDQyAAACAGlzb21pc28yYXZjMW1wNDEAAAAIZnJlZQAACKBtZGF0AAAC8wYF///v3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlIDE0MiByMjQ3OSBkZDc5YTYxIC0gSC4yNjQvTVBFRy00IEFWQyBjb2RlYyAtIENvcHlsZWZ0IDIwMDMtMjAxNCAtIGh0dHA6Ly93d3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG9wdGlvbnM6IGNhYmFjPTEgcmVmPTEgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MToweDExMSBtZT1oZXggc3VibWU9MiBwc3k9MSBwc3lfcmQ9MS4wMDowLjAwIG1peGVkX3JlZj0wIG1lX3JhbmdlPTE2IGNocm9tYV9tZT0xIHRyZWxsaXM9MCA4eDhkY3Q9MCBjcW09MCBkZWFkem9uZT0yMSwxMSBmYXN0X3Bza2lwPTEgY2hyb21hX3FwX29mZnNldD0wIHRocmVhZHM9NiBsb29rYWhlYWRfdGhyZWFkcz0xIHNsaWNlZF90aHJlYWRzPTAgbnI9MCBkZWNpbWF0ZT0xIGludGVybGFjZWQ9MCBibHVyYXlfY29tcGF0PTAgY29uc3RyYWluZWRfaW50cmE9MCBiZnJhbWVzPTMgYl9weXJhbWlkPTIgYl9hZGFwdD0xIGJfYmlhcz0wIGRpcmVjdD0xIHdlaWdodGI9MSBvcGVuX2dvcD0wIHdlaWdodHA9MSBrZXlpbnQ9MzAwIGtleWludF9taW49MzAgc2NlbmVjdXQ9NDAgaW50cmFfcmVmcmVzaD0wIHJjX2xvb2thaGVhZD0xMCByYz1jcmYgbWJ0cmVlPTEgY3JmPTIwLjAgcWNvbXA9MC42MCBxcG1pbj0wIHFwbWF4PTY5IHFwc3RlcD00IHZidl9tYXhyYXRlPTIwMDAwIHZidl9idWZzaXplPTI1MDAwIGNyZl9tYXg9MC4wIG5hbF9ocmQ9bm9uZSBmaWxsZXI9MCBpcF9yYXRpbz0xLjQwIGFxPTE6MS4wMACAAAAAOWWIhAA3//p+C7v8tDDSTjf97w55i3SbRPO4ZY+hkjD5hbkAkL3zpJ6h/LR1CAABzgB1kqqzUorlhQAAAAxBmiQYhn/+qZYADLgAAAAJQZ5CQhX/AAj5IQADQGgcIQADQGgcAAAACQGeYUQn/wALKCEAA0BoHAAAAAkBnmNEJ/8ACykhAANAaBwhAANAaBwAAAANQZpoNExDP/6plgAMuSEAA0BoHAAAAAtBnoZFESwr/wAI+SEAA0BoHCEAA0BoHAAAAAkBnqVEJ/8ACykhAANAaBwAAAAJAZ6nRCf/AAsoIQADQGgcIQADQGgcAAAADUGarDRMQz/+qZYADLghAANAaBwAAAALQZ7KRRUsK/8ACPkhAANAaBwAAAAJAZ7pRCf/AAsoIQADQGgcIQADQGgcAAAACQGe60Qn/wALKCEAA0BoHAAAAA1BmvA0TEM//qmWAAy5IQADQGgcIQADQGgcAAAAC0GfDkUVLCv/AAj5IQADQGgcAAAACQGfLUQn/wALKSEAA0BoHCEAA0BoHAAAAAkBny9EJ/8ACyghAANAaBwAAAANQZs0NExDP/6plgAMuCEAA0BoHAAAAAtBn1JFFSwr/wAI+SEAA0BoHCEAA0BoHAAAAAkBn3FEJ/8ACyghAANAaBwAAAAJAZ9zRCf/AAsoIQADQGgcIQADQGgcAAAADUGbeDRMQz/+qZYADLkhAANAaBwAAAALQZ+WRRUsK/8ACPghAANAaBwhAANAaBwAAAAJAZ+1RCf/AAspIQADQGgcAAAACQGft0Qn/wALKSEAA0BoHCEAA0BoHAAAAA1Bm7w0TEM//qmWAAy4IQADQGgcAAAAC0Gf2kUVLCv/AAj5IQADQGgcAAAACQGf+UQn/wALKCEAA0BoHCEAA0BoHAAAAAkBn/tEJ/8ACykhAANAaBwAAAANQZvgNExDP/6plgAMuSEAA0BoHCEAA0BoHAAAAAtBnh5FFSwr/wAI+CEAA0BoHAAAAAkBnj1EJ/8ACyghAANAaBwhAANAaBwAAAAJAZ4/RCf/AAspIQADQGgcAAAADUGaJDRMQz/+qZYADLghAANAaBwAAAALQZ5CRRUsK/8ACPkhAANAaBwhAANAaBwAAAAJAZ5hRCf/AAsoIQADQGgcAAAACQGeY0Qn/wALKSEAA0BoHCEAA0BoHAAAAA1Bmmg0TEM//qmWAAy5IQADQGgcAAAAC0GehkUVLCv/AAj5IQADQGgcIQADQGgcAAAACQGepUQn/wALKSEAA0BoHAAAAAkBnqdEJ/8ACyghAANAaBwAAAANQZqsNExDP/6plgAMuCEAA0BoHCEAA0BoHAAAAAtBnspFFSwr/wAI+SEAA0BoHAAAAAkBnulEJ/8ACyghAANAaBwhAANAaBwAAAAJAZ7rRCf/AAsoIQADQGgcAAAADUGa8DRMQz/+qZYADLkhAANAaBwhAANAaBwAAAALQZ8ORRUsK/8ACPkhAANAaBwAAAAJAZ8tRCf/AAspIQADQGgcIQADQGgcAAAACQGfL0Qn/wALKCEAA0BoHAAAAA1BmzQ0TEM//qmWAAy4IQADQGgcAAAAC0GfUkUVLCv/AAj5IQADQGgcIQADQGgcAAAACQGfcUQn/wALKCEAA0BoHAAAAAkBn3NEJ/8ACyghAANAaBwhAANAaBwAAAANQZt4NExC//6plgAMuSEAA0BoHAAAAAtBn5ZFFSwr/wAI+CEAA0BoHCEAA0BoHAAAAAkBn7VEJ/8ACykhAANAaBwAAAAJAZ+3RCf/AAspIQADQGgcAAAADUGbuzRMQn/+nhAAYsAhAANAaBwhAANAaBwAAAAJQZ/aQhP/AAspIQADQGgcAAAACQGf+UQn/wALKCEAA0BoHCEAA0BoHCEAA0BoHCEAA0BoHCEAA0BoHCEAA0BoHAAACiFtb292AAAAbG12aGQAAAAA1YCCX9WAgl8AAAPoAAAH/AABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAGGlvZHMAAAAAEICAgAcAT////v7/AAAF+XRyYWsAAABcdGtoZAAAAAPVgIJf1YCCXwAAAAEAAAAAAAAH0AAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAygAAAMoAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAB9AAABdwAAEAAAAABXFtZGlhAAAAIG1kaGQAAAAA1YCCX9WAgl8AAV+QAAK/IFXEAAAAAAAtaGRscgAAAAAAAAAAdmlkZQAAAAAAAAAAAAAAAFZpZGVvSGFuZGxlcgAAAAUcbWluZgAAABR2bWhkAAAAAQAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybCAAAAABAAAE3HN0YmwAAACYc3RzZAAAAAAAAAABAAAAiGF2YzEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAygDKAEgAAABIAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY//8AAAAyYXZjQwFNQCj/4QAbZ01AKOyho3ySTUBAQFAAAAMAEAAr8gDxgxlgAQAEaO+G8gAAABhzdHRzAAAAAAAAAAEAAAA8AAALuAAAABRzdHNzAAAAAAAAAAEAAAABAAAB8GN0dHMAAAAAAAAAPAAAAAEAABdwAAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAAC7gAAAAAQAAF3AAAAABAAAAAAAAABxzdHNjAAAAAAAAAAEAAAABAAAAAQAAAAEAAAEEc3RzegAAAAAAAAAAAAAAPAAAAzQAAAAQAAAADQAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAANAAAADQAAAQBzdGNvAAAAAAAAADwAAAAwAAADZAAAA3QAAAONAAADoAAAA7kAAAPQAAAD6wAAA/4AAAQXAAAELgAABEMAAARcAAAEbwAABIwAAAShAAAEugAABM0AAATkAAAE/wAABRIAAAUrAAAFQgAABV0AAAVwAAAFiQAABaAAAAW1AAAFzgAABeEAAAX+AAAGEwAABiwAAAY/AAAGVgAABnEAAAaEAAAGnQAABrQAAAbPAAAG4gAABvUAAAcSAAAHJwAAB0AAAAdTAAAHcAAAB4UAAAeeAAAHsQAAB8gAAAfjAAAH9gAACA8AAAgmAAAIQQAACFQAAAhnAAAIhAAACJcAAAMsdHJhawAAAFx0a2hkAAAAA9WAgl/VgIJfAAAAAgAAAAAAAAf8AAAAAAAAAAAAAAABAQAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAACsm1kaWEAAAAgbWRoZAAAAADVgIJf1YCCXwAArEQAAWAAVcQAAAAAACdoZGxyAAAAAAAAAABzb3VuAAAAAAAAAAAAAAAAU3RlcmVvAAAAAmNtaW5mAAAAEHNtaGQAAAAAAAAAAAAAACRkaW5mAAAAHGRyZWYAAAAAAAAAAQAAAAx1cmwgAAAAAQAAAidzdGJsAAAAZ3N0c2QAAAAAAAAAAQAAAFdtcDRhAAAAAAAAAAEAAAAAAAAAAAACABAAAAAArEQAAAAAADNlc2RzAAAAAAOAgIAiAAIABICAgBRAFQAAAAADDUAAAAAABYCAgAISEAaAgIABAgAAABhzdHRzAAAAAAAAAAEAAABYAAAEAAAAABxzdHNjAAAAAAAAAAEAAAABAAAAAQAAAAEAAAAUc3RzegAAAAAAAAAGAAAAWAAAAXBzdGNvAAAAAAAAAFgAAAOBAAADhwAAA5oAAAOtAAADswAAA8oAAAPfAAAD5QAAA/gAAAQLAAAEEQAABCgAAAQ9AAAEUAAABFYAAARpAAAEgAAABIYAAASbAAAErgAABLQAAATHAAAE3gAABPMAAAT5AAAFDAAABR8AAAUlAAAFPAAABVEAAAVXAAAFagAABX0AAAWDAAAFmgAABa8AAAXCAAAFyAAABdsAAAXyAAAF+AAABg0AAAYgAAAGJgAABjkAAAZQAAAGZQAABmsAAAZ+AAAGkQAABpcAAAauAAAGwwAABskAAAbcAAAG7wAABwYAAAcMAAAHIQAABzQAAAc6AAAHTQAAB2QAAAdqAAAHfwAAB5IAAAeYAAAHqwAAB8IAAAfXAAAH3QAAB/AAAAgDAAAICQAACCAAAAg1AAAIOwAACE4AAAhhAAAIeAAACH4AAAiRAAAIpAAACKoAAAiwAAAItgAACLwAAAjCAAAAFnVkdGEAAAAObmFtZVN0ZXJlbwAAAHB1ZHRhAAAAaG1ldGEAAAAAAAAAIWhkbHIAAAAAAAAAAG1kaXJhcHBsAAAAAAAAAAAAAAAAO2lsc3QAAAAzqXRvbwAAACtkYXRhAAAAAQAAAABIYW5kQnJha2UgMC4xMC4yIDIwMTUwNjExMDA=';
2762
+ })
2763
+ ]);
2764
+ });
2765
+ });
2766
+ var NoSleep$1 = unwrapExports$$1(NoSleep);
2767
+ var nextDisplayId = 1000;
2768
+ var defaultLeftBounds = [0, 0, 0.5, 1];
2769
+ var defaultRightBounds = [0.5, 0, 0.5, 1];
2770
+ var raf = window.requestAnimationFrame;
2771
+ var caf = window.cancelAnimationFrame;
2772
+ function VRFrameData() {
2773
+ this.leftProjectionMatrix = new Float32Array(16);
2774
+ this.leftViewMatrix = new Float32Array(16);
2775
+ this.rightProjectionMatrix = new Float32Array(16);
2776
+ this.rightViewMatrix = new Float32Array(16);
2777
+ this.pose = null;
2778
+ }
2779
+ function VRDisplayCapabilities(config) {
2780
+ Object.defineProperties(this, {
2781
+ hasPosition: {
2782
+ writable: false, enumerable: true, value: config.hasPosition
2783
+ },
2784
+ hasExternalDisplay: {
2785
+ writable: false, enumerable: true, value: config.hasExternalDisplay
2786
+ },
2787
+ canPresent: {
2788
+ writable: false, enumerable: true, value: config.canPresent
2789
+ },
2790
+ maxLayers: {
2791
+ writable: false, enumerable: true, value: config.maxLayers
2792
+ },
2793
+ hasOrientation: {
2794
+ enumerable: true, get: function get() {
2795
+ deprecateWarning('VRDisplayCapabilities.prototype.hasOrientation', 'VRDisplay.prototype.getFrameData');
2796
+ return config.hasOrientation;
2797
+ }
2798
+ }
2799
+ });
2800
+ }
2801
+ function VRDisplay(config) {
2802
+ config = config || {};
2803
+ var USE_WAKELOCK = 'wakelock' in config ? config.wakelock : true;
2804
+ this.isPolyfilled = true;
2805
+ this.displayId = nextDisplayId++;
2806
+ this.displayName = '';
2807
+ this.depthNear = 0.01;
2808
+ this.depthFar = 10000.0;
2809
+ this.isPresenting = false;
2810
+ Object.defineProperty(this, 'isConnected', {
2811
+ get: function get() {
2812
+ deprecateWarning('VRDisplay.prototype.isConnected', 'VRDisplayCapabilities.prototype.hasExternalDisplay');
2813
+ return false;
2814
+ }
2815
+ });
2816
+ this.capabilities = new VRDisplayCapabilities({
2817
+ hasPosition: false,
2818
+ hasOrientation: false,
2819
+ hasExternalDisplay: false,
2820
+ canPresent: false,
2821
+ maxLayers: 1
2822
+ });
2823
+ this.stageParameters = null;
2824
+ this.waitingForPresent_ = false;
2825
+ this.layer_ = null;
2826
+ this.originalParent_ = null;
2827
+ this.fullscreenElement_ = null;
2828
+ this.fullscreenWrapper_ = null;
2829
+ this.fullscreenElementCachedStyle_ = null;
2830
+ this.fullscreenEventTarget_ = null;
2831
+ this.fullscreenChangeHandler_ = null;
2832
+ this.fullscreenErrorHandler_ = null;
2833
+ if (USE_WAKELOCK && isMobile()) {
2834
+ this.wakelock_ = new NoSleep$1();
2835
+ }
2836
+ }
2837
+ VRDisplay.prototype.getFrameData = function (frameData) {
2838
+ return frameDataFromPose(frameData, this._getPose(), this);
2839
+ };
2840
+ VRDisplay.prototype.getPose = function () {
2841
+ deprecateWarning('VRDisplay.prototype.getPose', 'VRDisplay.prototype.getFrameData');
2842
+ return this._getPose();
2843
+ };
2844
+ VRDisplay.prototype.resetPose = function () {
2845
+ deprecateWarning('VRDisplay.prototype.resetPose');
2846
+ return this._resetPose();
2847
+ };
2848
+ VRDisplay.prototype.getImmediatePose = function () {
2849
+ deprecateWarning('VRDisplay.prototype.getImmediatePose', 'VRDisplay.prototype.getFrameData');
2850
+ return this._getPose();
2851
+ };
2852
+ VRDisplay.prototype.requestAnimationFrame = function (callback) {
2853
+ return raf(callback);
2854
+ };
2855
+ VRDisplay.prototype.cancelAnimationFrame = function (id) {
2856
+ return caf(id);
2857
+ };
2858
+ VRDisplay.prototype.wrapForFullscreen = function (element) {
2859
+ if (isIOS()) {
2860
+ return element;
2861
+ }
2862
+ if (!this.fullscreenWrapper_) {
2863
+ this.fullscreenWrapper_ = document.createElement('div');
2864
+ var cssProperties = ['height: ' + Math.min(screen.height, screen.width) + 'px !important', 'top: 0 !important', 'left: 0 !important', 'right: 0 !important', 'border: 0', 'margin: 0', 'padding: 0', 'z-index: 999999 !important', 'position: fixed'];
2865
+ this.fullscreenWrapper_.setAttribute('style', cssProperties.join('; ') + ';');
2866
+ this.fullscreenWrapper_.classList.add('webvr-polyfill-fullscreen-wrapper');
2867
+ }
2868
+ if (this.fullscreenElement_ == element) {
2869
+ return this.fullscreenWrapper_;
2870
+ }
2871
+ if (this.fullscreenElement_) {
2872
+ if (this.originalParent_) {
2873
+ this.originalParent_.appendChild(this.fullscreenElement_);
2874
+ } else {
2875
+ this.fullscreenElement_.parentElement.removeChild(this.fullscreenElement_);
2876
+ }
2877
+ }
2878
+ this.fullscreenElement_ = element;
2879
+ this.originalParent_ = element.parentElement;
2880
+ if (!this.originalParent_) {
2881
+ document.body.appendChild(element);
2882
+ }
2883
+ if (!this.fullscreenWrapper_.parentElement) {
2884
+ var parent = this.fullscreenElement_.parentElement;
2885
+ parent.insertBefore(this.fullscreenWrapper_, this.fullscreenElement_);
2886
+ parent.removeChild(this.fullscreenElement_);
2887
+ }
2888
+ this.fullscreenWrapper_.insertBefore(this.fullscreenElement_, this.fullscreenWrapper_.firstChild);
2889
+ this.fullscreenElementCachedStyle_ = this.fullscreenElement_.getAttribute('style');
2890
+ var self = this;
2891
+ function applyFullscreenElementStyle() {
2892
+ if (!self.fullscreenElement_) {
2893
+ return;
2894
+ }
2895
+ var cssProperties = ['position: absolute', 'top: 0', 'left: 0', 'width: ' + Math.max(screen.width, screen.height) + 'px', 'height: ' + Math.min(screen.height, screen.width) + 'px', 'border: 0', 'margin: 0', 'padding: 0'];
2896
+ self.fullscreenElement_.setAttribute('style', cssProperties.join('; ') + ';');
2897
+ }
2898
+ applyFullscreenElementStyle();
2899
+ return this.fullscreenWrapper_;
2900
+ };
2901
+ VRDisplay.prototype.removeFullscreenWrapper = function () {
2902
+ if (!this.fullscreenElement_) {
2903
+ return;
2904
+ }
2905
+ var element = this.fullscreenElement_;
2906
+ if (this.fullscreenElementCachedStyle_) {
2907
+ element.setAttribute('style', this.fullscreenElementCachedStyle_);
2908
+ } else {
2909
+ element.removeAttribute('style');
2910
+ }
2911
+ this.fullscreenElement_ = null;
2912
+ this.fullscreenElementCachedStyle_ = null;
2913
+ var parent = this.fullscreenWrapper_.parentElement;
2914
+ this.fullscreenWrapper_.removeChild(element);
2915
+ if (this.originalParent_ === parent) {
2916
+ parent.insertBefore(element, this.fullscreenWrapper_);
2917
+ }
2918
+ else if (this.originalParent_) {
2919
+ this.originalParent_.appendChild(element);
2920
+ }
2921
+ parent.removeChild(this.fullscreenWrapper_);
2922
+ return element;
2923
+ };
2924
+ VRDisplay.prototype.requestPresent = function (layers) {
2925
+ var wasPresenting = this.isPresenting;
2926
+ var self = this;
2927
+ if (!(layers instanceof Array)) {
2928
+ deprecateWarning('VRDisplay.prototype.requestPresent with non-array argument', 'an array of VRLayers as the first argument');
2929
+ layers = [layers];
2930
+ }
2931
+ return new Promise(function (resolve, reject) {
2932
+ if (!self.capabilities.canPresent) {
2933
+ reject(new Error('VRDisplay is not capable of presenting.'));
2934
+ return;
2935
+ }
2936
+ if (layers.length == 0 || layers.length > self.capabilities.maxLayers) {
2937
+ reject(new Error('Invalid number of layers.'));
2938
+ return;
2939
+ }
2940
+ var incomingLayer = layers[0];
2941
+ if (!incomingLayer.source) {
2942
+ resolve();
2943
+ return;
2944
+ }
2945
+ var leftBounds = incomingLayer.leftBounds || defaultLeftBounds;
2946
+ var rightBounds = incomingLayer.rightBounds || defaultRightBounds;
2947
+ if (wasPresenting) {
2948
+ var layer = self.layer_;
2949
+ if (layer.source !== incomingLayer.source) {
2950
+ layer.source = incomingLayer.source;
2951
+ }
2952
+ for (var i = 0; i < 4; i++) {
2953
+ layer.leftBounds[i] = leftBounds[i];
2954
+ layer.rightBounds[i] = rightBounds[i];
2955
+ }
2956
+ self.wrapForFullscreen(self.layer_.source);
2957
+ self.updatePresent_();
2958
+ resolve();
2959
+ return;
2960
+ }
2961
+ self.layer_ = {
2962
+ predistorted: incomingLayer.predistorted,
2963
+ source: incomingLayer.source,
2964
+ leftBounds: leftBounds.slice(0),
2965
+ rightBounds: rightBounds.slice(0)
2966
+ };
2967
+ self.waitingForPresent_ = false;
2968
+ if (self.layer_ && self.layer_.source) {
2969
+ var fullscreenElement = self.wrapForFullscreen(self.layer_.source);
2970
+ var onFullscreenChange = function onFullscreenChange() {
2971
+ var actualFullscreenElement = getFullscreenElement();
2972
+ self.isPresenting = fullscreenElement === actualFullscreenElement;
2973
+ if (self.isPresenting) {
2974
+ if (screen.orientation && screen.orientation.lock) {
2975
+ screen.orientation.lock('landscape-primary').catch(function (error) {
2976
+ console.error('screen.orientation.lock() failed due to', error.message);
2977
+ });
2978
+ }
2979
+ self.waitingForPresent_ = false;
2980
+ self.beginPresent_();
2981
+ resolve();
2982
+ } else {
2983
+ if (screen.orientation && screen.orientation.unlock) {
2984
+ screen.orientation.unlock();
2985
+ }
2986
+ self.removeFullscreenWrapper();
2987
+ self.disableWakeLock();
2988
+ self.endPresent_();
2989
+ self.removeFullscreenListeners_();
2990
+ }
2991
+ self.fireVRDisplayPresentChange_();
2992
+ };
2993
+ var onFullscreenError = function onFullscreenError() {
2994
+ if (!self.waitingForPresent_) {
2995
+ return;
2996
+ }
2997
+ self.removeFullscreenWrapper();
2998
+ self.removeFullscreenListeners_();
2999
+ self.disableWakeLock();
3000
+ self.waitingForPresent_ = false;
3001
+ self.isPresenting = false;
3002
+ reject(new Error('Unable to present.'));
3003
+ };
3004
+ self.addFullscreenListeners_(fullscreenElement, onFullscreenChange, onFullscreenError);
3005
+ if (requestFullscreen(fullscreenElement)) {
3006
+ self.enableWakeLock();
3007
+ self.waitingForPresent_ = true;
3008
+ } else if (isIOS() || isWebViewAndroid()) {
3009
+ self.enableWakeLock();
3010
+ self.isPresenting = true;
3011
+ self.beginPresent_();
3012
+ self.fireVRDisplayPresentChange_();
3013
+ resolve();
3014
+ }
3015
+ }
3016
+ if (!self.waitingForPresent_ && !isIOS()) {
3017
+ exitFullscreen();
3018
+ reject(new Error('Unable to present.'));
3019
+ }
3020
+ });
3021
+ };
3022
+ VRDisplay.prototype.exitPresent = function () {
3023
+ var wasPresenting = this.isPresenting;
3024
+ var self = this;
3025
+ this.isPresenting = false;
3026
+ this.layer_ = null;
3027
+ this.disableWakeLock();
3028
+ return new Promise(function (resolve, reject) {
3029
+ if (wasPresenting) {
3030
+ if (!exitFullscreen() && isIOS()) {
3031
+ self.endPresent_();
3032
+ self.fireVRDisplayPresentChange_();
3033
+ }
3034
+ if (isWebViewAndroid()) {
3035
+ self.removeFullscreenWrapper();
3036
+ self.removeFullscreenListeners_();
3037
+ self.endPresent_();
3038
+ self.fireVRDisplayPresentChange_();
3039
+ }
3040
+ resolve();
3041
+ } else {
3042
+ reject(new Error('Was not presenting to VRDisplay.'));
3043
+ }
3044
+ });
3045
+ };
3046
+ VRDisplay.prototype.getLayers = function () {
3047
+ if (this.layer_) {
3048
+ return [this.layer_];
3049
+ }
3050
+ return [];
3051
+ };
3052
+ VRDisplay.prototype.fireVRDisplayPresentChange_ = function () {
3053
+ var event = new CustomEvent('vrdisplaypresentchange', { detail: { display: this } });
3054
+ window.dispatchEvent(event);
3055
+ };
3056
+ VRDisplay.prototype.fireVRDisplayConnect_ = function () {
3057
+ var event = new CustomEvent('vrdisplayconnect', { detail: { display: this } });
3058
+ window.dispatchEvent(event);
3059
+ };
3060
+ VRDisplay.prototype.addFullscreenListeners_ = function (element, changeHandler, errorHandler) {
3061
+ this.removeFullscreenListeners_();
3062
+ this.fullscreenEventTarget_ = element;
3063
+ this.fullscreenChangeHandler_ = changeHandler;
3064
+ this.fullscreenErrorHandler_ = errorHandler;
3065
+ if (changeHandler) {
3066
+ if (document.fullscreenEnabled) {
3067
+ element.addEventListener('fullscreenchange', changeHandler, false);
3068
+ } else if (document.webkitFullscreenEnabled) {
3069
+ element.addEventListener('webkitfullscreenchange', changeHandler, false);
3070
+ } else if (document.mozFullScreenEnabled) {
3071
+ document.addEventListener('mozfullscreenchange', changeHandler, false);
3072
+ } else if (document.msFullscreenEnabled) {
3073
+ element.addEventListener('msfullscreenchange', changeHandler, false);
3074
+ }
3075
+ }
3076
+ if (errorHandler) {
3077
+ if (document.fullscreenEnabled) {
3078
+ element.addEventListener('fullscreenerror', errorHandler, false);
3079
+ } else if (document.webkitFullscreenEnabled) {
3080
+ element.addEventListener('webkitfullscreenerror', errorHandler, false);
3081
+ } else if (document.mozFullScreenEnabled) {
3082
+ document.addEventListener('mozfullscreenerror', errorHandler, false);
3083
+ } else if (document.msFullscreenEnabled) {
3084
+ element.addEventListener('msfullscreenerror', errorHandler, false);
3085
+ }
3086
+ }
3087
+ };
3088
+ VRDisplay.prototype.removeFullscreenListeners_ = function () {
3089
+ if (!this.fullscreenEventTarget_) return;
3090
+ var element = this.fullscreenEventTarget_;
3091
+ if (this.fullscreenChangeHandler_) {
3092
+ var changeHandler = this.fullscreenChangeHandler_;
3093
+ element.removeEventListener('fullscreenchange', changeHandler, false);
3094
+ element.removeEventListener('webkitfullscreenchange', changeHandler, false);
3095
+ document.removeEventListener('mozfullscreenchange', changeHandler, false);
3096
+ element.removeEventListener('msfullscreenchange', changeHandler, false);
3097
+ }
3098
+ if (this.fullscreenErrorHandler_) {
3099
+ var errorHandler = this.fullscreenErrorHandler_;
3100
+ element.removeEventListener('fullscreenerror', errorHandler, false);
3101
+ element.removeEventListener('webkitfullscreenerror', errorHandler, false);
3102
+ document.removeEventListener('mozfullscreenerror', errorHandler, false);
3103
+ element.removeEventListener('msfullscreenerror', errorHandler, false);
3104
+ }
3105
+ this.fullscreenEventTarget_ = null;
3106
+ this.fullscreenChangeHandler_ = null;
3107
+ this.fullscreenErrorHandler_ = null;
3108
+ };
3109
+ VRDisplay.prototype.enableWakeLock = function () {
3110
+ if (this.wakelock_) {
3111
+ this.wakelock_.enable();
3112
+ }
3113
+ };
3114
+ VRDisplay.prototype.disableWakeLock = function () {
3115
+ if (this.wakelock_) {
3116
+ this.wakelock_.disable();
3117
+ }
3118
+ };
3119
+ VRDisplay.prototype.beginPresent_ = function () {
3120
+ };
3121
+ VRDisplay.prototype.endPresent_ = function () {
3122
+ };
3123
+ VRDisplay.prototype.submitFrame = function (pose) {
3124
+ };
3125
+ VRDisplay.prototype.getEyeParameters = function (whichEye) {
3126
+ return null;
3127
+ };
3128
+ var config = {
3129
+ ADDITIONAL_VIEWERS: [],
3130
+ DEFAULT_VIEWER: '',
3131
+ MOBILE_WAKE_LOCK: true,
3132
+ DEBUG: false,
3133
+ DPDB_URL: 'https://dpdb.webvr.rocks/dpdb.json',
3134
+ K_FILTER: 0.98,
3135
+ PREDICTION_TIME_S: 0.040,
3136
+ CARDBOARD_UI_DISABLED: false,
3137
+ ROTATE_INSTRUCTIONS_DISABLED: false,
3138
+ YAW_ONLY: false,
3139
+ BUFFER_SCALE: 0.5,
3140
+ DIRTY_SUBMIT_FRAME_BINDINGS: false
3141
+ };
3142
+ var Eye = {
3143
+ LEFT: 'left',
3144
+ RIGHT: 'right'
3145
+ };
3146
+ function CardboardVRDisplay(config$$1) {
3147
+ var defaults = extend({}, config);
3148
+ config$$1 = extend(defaults, config$$1 || {});
3149
+ VRDisplay.call(this, {
3150
+ wakelock: config$$1.MOBILE_WAKE_LOCK
3151
+ });
3152
+ this.config = config$$1;
3153
+ this.displayName = 'Cardboard VRDisplay';
3154
+ this.capabilities = new VRDisplayCapabilities({
3155
+ hasPosition: false,
3156
+ hasOrientation: true,
3157
+ hasExternalDisplay: false,
3158
+ canPresent: true,
3159
+ maxLayers: 1
3160
+ });
3161
+ this.stageParameters = null;
3162
+ this.bufferScale_ = this.config.BUFFER_SCALE;
3163
+ this.poseSensor_ = new PoseSensor(this.config);
3164
+ this.distorter_ = null;
3165
+ this.cardboardUI_ = null;
3166
+ this.dpdb_ = new Dpdb(this.config.DPDB_URL, this.onDeviceParamsUpdated_.bind(this));
3167
+ this.deviceInfo_ = new DeviceInfo(this.dpdb_.getDeviceParams(), config$$1.ADDITIONAL_VIEWERS);
3168
+ this.viewerSelector_ = new ViewerSelector(config$$1.DEFAULT_VIEWER);
3169
+ this.viewerSelector_.onChange(this.onViewerChanged_.bind(this));
3170
+ this.deviceInfo_.setViewer(this.viewerSelector_.getCurrentViewer());
3171
+ if (!this.config.ROTATE_INSTRUCTIONS_DISABLED) {
3172
+ this.rotateInstructions_ = new RotateInstructions();
3173
+ }
3174
+ if (isIOS()) {
3175
+ window.addEventListener('resize', this.onResize_.bind(this));
3176
+ }
3177
+ }
3178
+ CardboardVRDisplay.prototype = Object.create(VRDisplay.prototype);
3179
+ CardboardVRDisplay.prototype._getPose = function () {
3180
+ return {
3181
+ position: null,
3182
+ orientation: this.poseSensor_.getOrientation(),
3183
+ linearVelocity: null,
3184
+ linearAcceleration: null,
3185
+ angularVelocity: null,
3186
+ angularAcceleration: null
3187
+ };
3188
+ };
3189
+ CardboardVRDisplay.prototype._resetPose = function () {
3190
+ if (this.poseSensor_.resetPose) {
3191
+ this.poseSensor_.resetPose();
3192
+ }
3193
+ };
3194
+ CardboardVRDisplay.prototype._getFieldOfView = function (whichEye) {
3195
+ var fieldOfView;
3196
+ if (whichEye == Eye.LEFT) {
3197
+ fieldOfView = this.deviceInfo_.getFieldOfViewLeftEye();
3198
+ } else if (whichEye == Eye.RIGHT) {
3199
+ fieldOfView = this.deviceInfo_.getFieldOfViewRightEye();
3200
+ } else {
3201
+ console.error('Invalid eye provided: %s', whichEye);
3202
+ return null;
3203
+ }
3204
+ return fieldOfView;
3205
+ };
3206
+ CardboardVRDisplay.prototype._getEyeOffset = function (whichEye) {
3207
+ var offset;
3208
+ if (whichEye == Eye.LEFT) {
3209
+ offset = [-this.deviceInfo_.viewer.interLensDistance * 0.5, 0.0, 0.0];
3210
+ } else if (whichEye == Eye.RIGHT) {
3211
+ offset = [this.deviceInfo_.viewer.interLensDistance * 0.5, 0.0, 0.0];
3212
+ } else {
3213
+ console.error('Invalid eye provided: %s', whichEye);
3214
+ return null;
3215
+ }
3216
+ return offset;
3217
+ };
3218
+ CardboardVRDisplay.prototype.getEyeParameters = function (whichEye) {
3219
+ var offset = this._getEyeOffset(whichEye);
3220
+ var fieldOfView = this._getFieldOfView(whichEye);
3221
+ var eyeParams = {
3222
+ offset: offset,
3223
+ renderWidth: this.deviceInfo_.device.width * 0.5 * this.bufferScale_,
3224
+ renderHeight: this.deviceInfo_.device.height * this.bufferScale_
3225
+ };
3226
+ Object.defineProperty(eyeParams, 'fieldOfView', {
3227
+ enumerable: true,
3228
+ get: function get() {
3229
+ deprecateWarning('VRFieldOfView', 'VRFrameData\'s projection matrices');
3230
+ return fieldOfView;
3231
+ }
3232
+ });
3233
+ return eyeParams;
3234
+ };
3235
+ CardboardVRDisplay.prototype.onDeviceParamsUpdated_ = function (newParams) {
3236
+ if (this.config.DEBUG) {
3237
+ console.log('DPDB reported that device params were updated.');
3238
+ }
3239
+ this.deviceInfo_.updateDeviceParams(newParams);
3240
+ if (this.distorter_) {
3241
+ this.distorter_.updateDeviceInfo(this.deviceInfo_);
3242
+ }
3243
+ };
3244
+ CardboardVRDisplay.prototype.updateBounds_ = function () {
3245
+ if (this.layer_ && this.distorter_ && (this.layer_.leftBounds || this.layer_.rightBounds)) {
3246
+ this.distorter_.setTextureBounds(this.layer_.leftBounds, this.layer_.rightBounds);
3247
+ }
3248
+ };
3249
+ CardboardVRDisplay.prototype.beginPresent_ = function () {
3250
+ var gl = this.layer_.source.getContext('webgl');
3251
+ if (!gl) gl = this.layer_.source.getContext('experimental-webgl');
3252
+ if (!gl) gl = this.layer_.source.getContext('webgl2');
3253
+ if (!gl) return;
3254
+ if (this.layer_.predistorted) {
3255
+ if (!this.config.CARDBOARD_UI_DISABLED) {
3256
+ gl.canvas.width = getScreenWidth() * this.bufferScale_;
3257
+ gl.canvas.height = getScreenHeight() * this.bufferScale_;
3258
+ this.cardboardUI_ = new CardboardUI(gl);
3259
+ }
3260
+ } else {
3261
+ if (!this.config.CARDBOARD_UI_DISABLED) {
3262
+ this.cardboardUI_ = new CardboardUI(gl);
3263
+ }
3264
+ this.distorter_ = new CardboardDistorter(gl, this.cardboardUI_, this.config.BUFFER_SCALE, this.config.DIRTY_SUBMIT_FRAME_BINDINGS);
3265
+ this.distorter_.updateDeviceInfo(this.deviceInfo_);
3266
+ }
3267
+ if (this.cardboardUI_) {
3268
+ this.cardboardUI_.listen(function (e) {
3269
+ this.viewerSelector_.show(this.layer_.source.parentElement);
3270
+ e.stopPropagation();
3271
+ e.preventDefault();
3272
+ }.bind(this), function (e) {
3273
+ this.exitPresent();
3274
+ e.stopPropagation();
3275
+ e.preventDefault();
3276
+ }.bind(this));
3277
+ }
3278
+ if (this.rotateInstructions_) {
3279
+ if (isLandscapeMode() && isMobile()) {
3280
+ this.rotateInstructions_.showTemporarily(3000, this.layer_.source.parentElement);
3281
+ } else {
3282
+ this.rotateInstructions_.update();
3283
+ }
3284
+ }
3285
+ this.orientationHandler = this.onOrientationChange_.bind(this);
3286
+ window.addEventListener('orientationchange', this.orientationHandler);
3287
+ this.vrdisplaypresentchangeHandler = this.updateBounds_.bind(this);
3288
+ window.addEventListener('vrdisplaypresentchange', this.vrdisplaypresentchangeHandler);
3289
+ this.fireVRDisplayDeviceParamsChange_();
3290
+ };
3291
+ CardboardVRDisplay.prototype.endPresent_ = function () {
3292
+ if (this.distorter_) {
3293
+ this.distorter_.destroy();
3294
+ this.distorter_ = null;
3295
+ }
3296
+ if (this.cardboardUI_) {
3297
+ this.cardboardUI_.destroy();
3298
+ this.cardboardUI_ = null;
3299
+ }
3300
+ if (this.rotateInstructions_) {
3301
+ this.rotateInstructions_.hide();
3302
+ }
3303
+ this.viewerSelector_.hide();
3304
+ window.removeEventListener('orientationchange', this.orientationHandler);
3305
+ window.removeEventListener('vrdisplaypresentchange', this.vrdisplaypresentchangeHandler);
3306
+ };
3307
+ CardboardVRDisplay.prototype.updatePresent_ = function () {
3308
+ this.endPresent_();
3309
+ this.beginPresent_();
3310
+ };
3311
+ CardboardVRDisplay.prototype.submitFrame = function (pose) {
3312
+ if (this.distorter_) {
3313
+ this.updateBounds_();
3314
+ this.distorter_.submitFrame();
3315
+ } else if (this.cardboardUI_ && this.layer_) {
3316
+ var canvas = this.layer_.source.getContext('webgl').canvas;
3317
+ if (canvas.width != this.lastWidth || canvas.height != this.lastHeight) {
3318
+ this.cardboardUI_.onResize();
3319
+ }
3320
+ this.lastWidth = canvas.width;
3321
+ this.lastHeight = canvas.height;
3322
+ this.cardboardUI_.render();
3323
+ }
3324
+ };
3325
+ CardboardVRDisplay.prototype.onOrientationChange_ = function (e) {
3326
+ this.viewerSelector_.hide();
3327
+ if (this.rotateInstructions_) {
3328
+ this.rotateInstructions_.update();
3329
+ }
3330
+ this.onResize_();
3331
+ };
3332
+ CardboardVRDisplay.prototype.onResize_ = function (e) {
3333
+ if (this.layer_) {
3334
+ var gl = this.layer_.source.getContext('webgl');
3335
+ var cssProperties = ['position: absolute', 'top: 0', 'left: 0',
3336
+ 'width: 100vw', 'height: 100vh', 'border: 0', 'margin: 0',
3337
+ 'padding: 0px', 'box-sizing: content-box'];
3338
+ gl.canvas.setAttribute('style', cssProperties.join('; ') + ';');
3339
+ safariCssSizeWorkaround(gl.canvas);
3340
+ }
3341
+ };
3342
+ CardboardVRDisplay.prototype.onViewerChanged_ = function (viewer) {
3343
+ this.deviceInfo_.setViewer(viewer);
3344
+ if (this.distorter_) {
3345
+ this.distorter_.updateDeviceInfo(this.deviceInfo_);
3346
+ }
3347
+ this.fireVRDisplayDeviceParamsChange_();
3348
+ };
3349
+ CardboardVRDisplay.prototype.fireVRDisplayDeviceParamsChange_ = function () {
3350
+ var event = new CustomEvent('vrdisplaydeviceparamschange', {
3351
+ detail: {
3352
+ vrdisplay: this,
3353
+ deviceInfo: this.deviceInfo_
3354
+ }
3355
+ });
3356
+ window.dispatchEvent(event);
3357
+ };
3358
+ CardboardVRDisplay.VRFrameData = VRFrameData;
3359
+ CardboardVRDisplay.VRDisplay = VRDisplay;
3360
+ return CardboardVRDisplay;
3361
+ })));
3362
+ });
3363
+ var CardboardVRDisplay = unwrapExports(cardboardVrDisplay);
3364
+
3365
+ var version = "0.10.7";
3366
+
3367
+ var DefaultConfig = {
3368
+ ADDITIONAL_VIEWERS: [],
3369
+ DEFAULT_VIEWER: '',
3370
+ PROVIDE_MOBILE_VRDISPLAY: true,
3371
+ GET_VR_DISPLAYS_TIMEOUT: 1000,
3372
+ MOBILE_WAKE_LOCK: true,
3373
+ DEBUG: false,
3374
+ DPDB_URL: 'https://dpdb.webvr.rocks/dpdb.json',
3375
+ K_FILTER: 0.98,
3376
+ PREDICTION_TIME_S: 0.040,
3377
+ CARDBOARD_UI_DISABLED: false,
3378
+ ROTATE_INSTRUCTIONS_DISABLED: false,
3379
+ YAW_ONLY: false,
3380
+ BUFFER_SCALE: 0.5,
3381
+ DIRTY_SUBMIT_FRAME_BINDINGS: false
3382
+ };
3383
+
3384
+ function WebVRPolyfill(config) {
3385
+ this.config = extend(extend({}, DefaultConfig), config);
3386
+ this.polyfillDisplays = [];
3387
+ this.enabled = false;
3388
+ this.hasNative = 'getVRDisplays' in navigator;
3389
+ this.native = {};
3390
+ this.native.getVRDisplays = navigator.getVRDisplays;
3391
+ this.native.VRFrameData = window.VRFrameData;
3392
+ this.native.VRDisplay = window.VRDisplay;
3393
+ if (!this.hasNative || this.config.PROVIDE_MOBILE_VRDISPLAY && isMobile()) {
3394
+ this.enable();
3395
+ this.getVRDisplays().then(function (displays) {
3396
+ if (displays && displays[0] && displays[0].fireVRDisplayConnect_) {
3397
+ displays[0].fireVRDisplayConnect_();
3398
+ }
3399
+ });
3400
+ }
3401
+ }
3402
+ WebVRPolyfill.prototype.getPolyfillDisplays = function () {
3403
+ if (this._polyfillDisplaysPopulated) {
3404
+ return this.polyfillDisplays;
3405
+ }
3406
+ if (isMobile()) {
3407
+ var vrDisplay = new CardboardVRDisplay({
3408
+ ADDITIONAL_VIEWERS: this.config.ADDITIONAL_VIEWERS,
3409
+ DEFAULT_VIEWER: this.config.DEFAULT_VIEWER,
3410
+ MOBILE_WAKE_LOCK: this.config.MOBILE_WAKE_LOCK,
3411
+ DEBUG: this.config.DEBUG,
3412
+ DPDB_URL: this.config.DPDB_URL,
3413
+ CARDBOARD_UI_DISABLED: this.config.CARDBOARD_UI_DISABLED,
3414
+ K_FILTER: this.config.K_FILTER,
3415
+ PREDICTION_TIME_S: this.config.PREDICTION_TIME_S,
3416
+ ROTATE_INSTRUCTIONS_DISABLED: this.config.ROTATE_INSTRUCTIONS_DISABLED,
3417
+ YAW_ONLY: this.config.YAW_ONLY,
3418
+ BUFFER_SCALE: this.config.BUFFER_SCALE,
3419
+ DIRTY_SUBMIT_FRAME_BINDINGS: this.config.DIRTY_SUBMIT_FRAME_BINDINGS
3420
+ });
3421
+ this.polyfillDisplays.push(vrDisplay);
3422
+ }
3423
+ this._polyfillDisplaysPopulated = true;
3424
+ return this.polyfillDisplays;
3425
+ };
3426
+ WebVRPolyfill.prototype.enable = function () {
3427
+ this.enabled = true;
3428
+ if (this.hasNative && this.native.VRFrameData) {
3429
+ var NativeVRFrameData = this.native.VRFrameData;
3430
+ var nativeFrameData = new this.native.VRFrameData();
3431
+ var nativeGetFrameData = this.native.VRDisplay.prototype.getFrameData;
3432
+ window.VRDisplay.prototype.getFrameData = function (frameData) {
3433
+ if (frameData instanceof NativeVRFrameData) {
3434
+ nativeGetFrameData.call(this, frameData);
3435
+ return;
3436
+ }
3437
+ nativeGetFrameData.call(this, nativeFrameData);
3438
+ frameData.pose = nativeFrameData.pose;
3439
+ copyArray(nativeFrameData.leftProjectionMatrix, frameData.leftProjectionMatrix);
3440
+ copyArray(nativeFrameData.rightProjectionMatrix, frameData.rightProjectionMatrix);
3441
+ copyArray(nativeFrameData.leftViewMatrix, frameData.leftViewMatrix);
3442
+ copyArray(nativeFrameData.rightViewMatrix, frameData.rightViewMatrix);
3443
+ };
3444
+ }
3445
+ navigator.getVRDisplays = this.getVRDisplays.bind(this);
3446
+ window.VRDisplay = CardboardVRDisplay.VRDisplay;
3447
+ window.VRFrameData = CardboardVRDisplay.VRFrameData;
3448
+ };
3449
+ WebVRPolyfill.prototype.getVRDisplays = function () {
3450
+ var _this = this;
3451
+ var config = this.config;
3452
+ if (!this.hasNative) {
3453
+ return Promise.resolve(this.getPolyfillDisplays());
3454
+ }
3455
+ var timeoutId;
3456
+ var vrDisplaysNative = this.native.getVRDisplays.call(navigator);
3457
+ var timeoutPromise = new Promise(function (resolve) {
3458
+ timeoutId = setTimeout(function () {
3459
+ console.warn('Native WebVR implementation detected, but `getVRDisplays()` failed to resolve. Falling back to polyfill.');
3460
+ resolve([]);
3461
+ }, config.GET_VR_DISPLAYS_TIMEOUT);
3462
+ });
3463
+ return race([vrDisplaysNative, timeoutPromise]).then(function (nativeDisplays) {
3464
+ clearTimeout(timeoutId);
3465
+ return nativeDisplays.length > 0 ? nativeDisplays : _this.getPolyfillDisplays();
3466
+ });
3467
+ };
3468
+ WebVRPolyfill.version = version;
3469
+ WebVRPolyfill.VRFrameData = CardboardVRDisplay.VRFrameData;
3470
+ WebVRPolyfill.VRDisplay = CardboardVRDisplay.VRDisplay;
3471
+
3472
+
3473
+ var webvrPolyfill = Object.freeze({
3474
+ default: WebVRPolyfill
3475
+ });
3476
+
3477
+ var require$$0 = ( webvrPolyfill && WebVRPolyfill ) || webvrPolyfill;
3478
+
3479
+ if (typeof commonjsGlobal !== 'undefined' && commonjsGlobal.window) {
3480
+ if (!commonjsGlobal.document) {
3481
+ commonjsGlobal.document = commonjsGlobal.window.document;
3482
+ }
3483
+ if (!commonjsGlobal.navigator) {
3484
+ commonjsGlobal.navigator = commonjsGlobal.window.navigator;
3485
+ }
3486
+ }
3487
+ var src = require$$0;
3488
+
3489
+ return src;
3490
+
3491
+ })));