(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.webvrui = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o\n
\n \n '; }; /** * Inject the CSS string to the head of the document * * @param {string} cssText the css to inject */ var injectCSS = exports.injectCSS = function injectCSS(cssText) { // Create the css var style = document.createElement('style'); style.innerHTML = cssText; var head = document.getElementsByTagName('head')[0]; head.insertBefore(style, head.firstChild); }; /** * Generate DOM element view for button * * @return {HTMLElement} * @param {Object} options */ var createDefaultView = exports.createDefaultView = function createDefaultView(options) { var fontSize = options.height / 3; if (options.injectCSS) { // Check that css isnt already injected if (!_WEBVR_UI_CSS_INJECTED[options.cssprefix]) { injectCSS(generateCSS(options, fontSize)); _WEBVR_UI_CSS_INJECTED[options.cssprefix] = true; } } var el = document.createElement('div'); el.innerHTML = generateInnerHTML(options.cssprefix, fontSize); return el.firstChild; }; var createVRIcon = exports.createVRIcon = function createVRIcon(cssPrefix, height) { var el = document.createElement('div'); el.innerHTML = generateVRIconString(cssPrefix, height); return el.firstChild; }; var createNoVRIcon = exports.createNoVRIcon = function createNoVRIcon(cssPrefix, height) { var el = document.createElement('div'); el.innerHTML = generateNoVRIconString(cssPrefix, height); return el.firstChild; }; var generateVRIconString = function generateVRIconString(cssPrefix, height) { var aspect = 28 / 18; return '\n \n '; }; var generateNoVRIconString = function generateNoVRIconString(cssPrefix, height) { var aspect = 28 / 18; return '\n \n \n \n '; }; /** * Generate the CSS string to inject * * @param {Object} options * @param {Number} [fontSize=18] * @return {string} */ var generateCSS = exports.generateCSS = function generateCSS(options) { var fontSize = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 18; var height = options.height; var borderWidth = 2; var borderColor = options.background ? options.background : options.color; var cssPrefix = options.cssprefix; var borderRadius = void 0; if (options.corners == 'round') { borderRadius = options.height / 2; } else if (options.corners == 'square') { borderRadius = 2; } else { borderRadius = options.corners; } return '\n @font-face {\n font-family: \'Karla\';\n font-style: normal;\n font-weight: 400;\n src: local(\'Karla\'), local(\'Karla-Regular\'), \n url(https://fonts.gstatic.com/s/karla/v5/31P4mP32i98D9CEnGyeX9Q.woff2) format(\'woff2\');\n unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;\n }\n @font-face {\n font-family: \'Karla\';\n font-style: normal;\n font-weight: 400;\n src: local(\'Karla\'), local(\'Karla-Regular\'), \n url(https://fonts.gstatic.com/s/karla/v5/Zi_e6rBgGqv33BWF8WTq8g.woff2) format(\'woff2\');\n unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, \n U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;\n }\n\n button.' + cssPrefix + '-button {\n font-family: \'Karla\', sans-serif;\n\n border: ' + borderColor + ' ' + borderWidth + 'px solid;\n border-radius: ' + borderRadius + 'px;\n box-sizing: border-box;\n background: ' + (options.background ? options.background : 'none') + ';\n\n height: ' + height + 'px;\n min-width: ' + fontSize * 9.6 + 'px;\n display: inline-block;\n position: relative;\n\n cursor: pointer;\n }\n \n button.' + cssPrefix + '-button:focus {\n outline: none;\n }\n\n /*\n * Logo\n */\n\n .' + cssPrefix + '-logo {\n width: ' + height + 'px;\n height: ' + height + 'px;\n position: absolute;\n top:0px;\n left:0px;\n width: ' + (height - 4) + 'px;\n height: ' + (height - 4) + 'px;\n }\n .' + cssPrefix + '-svg {\n fill: ' + options.color + ';\n margin-top: ' + ((height - fontSize * _LOGO_SCALE) / 2 - 2) + 'px;\n margin-left: ' + height / 3 + 'px;\n }\n .' + cssPrefix + '-svg-error {\n fill: ' + options.color + ';\n display:none;\n margin-top: ' + ((height - 28 / 18 * fontSize * _LOGO_SCALE) / 2 - 2) + 'px;\n margin-left: ' + height / 3 + 'px;\n }\n\n\n /*\n * Title\n */\n\n .' + cssPrefix + '-title {\n color: ' + options.color + ';\n position: relative;\n font-size: ' + fontSize + 'px;\n padding-left: ' + height * 1.05 + 'px;\n padding-right: ' + (borderRadius - 10 < 5 ? height / 3 : borderRadius - 10) + 'px;\n }\n\n /*\n * disabled\n */\n\n button.' + cssPrefix + '-button[disabled=true] {\n opacity: ' + options.disabledOpacity + ';\n }\n\n button.' + cssPrefix + '-button[disabled=true] > .' + cssPrefix + '-logo > .' + cssPrefix + '-svg {\n display:none;\n }\n\n button.' + cssPrefix + '-button[disabled=true] > .' + cssPrefix + '-logo > .' + cssPrefix + '-svg-error {\n display:initial;\n }\n '; }; },{}],5:[function(_dereq_,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); 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; }; }(); var _webvrManager = _dereq_('./webvr-manager'); var _webvrManager2 = _interopRequireDefault(_webvrManager); var _dom = _dereq_('./dom'); var _states = _dereq_('./states'); var _states2 = _interopRequireDefault(_states); var _eventemitter = _dereq_('eventemitter3'); var _eventemitter2 = _interopRequireDefault(_eventemitter); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } // Copyright 2016 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. /** * A button to allow easy-entry and messaging around a WebVR experience * @class */ var EnterVRButton = function (_EventEmitter) { _inherits(EnterVRButton, _EventEmitter); /** * Construct a new Enter VR Button * @constructor * @param {HTMLCanvasElement} sourceCanvas the canvas that you want to present in WebVR * @param {Object} [options] optional parameters * @param {HTMLElement} [options.domElement] provide your own domElement to bind to * @param {Boolean} [options.injectCSS=true] set to false if you want to write your own styles * @param {Function} [options.beforeEnter] should return a promise, opportunity to intercept request to enter * @param {Function} [options.beforeExit] should return a promise, opportunity to intercept request to exit * @param {Function} [options.onRequestStateChange] set to a function returning false to prevent default state changes * @param {string} [options.textEnterVRTitle] set the text for Enter VR * @param {string} [options.textVRNotFoundTitle] set the text for when a VR display is not found * @param {string} [options.textExitVRTitle] set the text for exiting VR * @param {string} [options.color] text and icon color * @param {string} [options.background] set to false for no brackground or a color * @param {string} [options.corners] set to 'round', 'square' or pixel value representing the corner radius * @param {string} [options.disabledOpacity] set opacity of button dom when disabled * @param {string} [options.cssprefix] set to change the css prefix from default 'webvr-ui' */ function EnterVRButton(sourceCanvas, options) { _classCallCheck(this, EnterVRButton); var _this = _possibleConstructorReturn(this, (EnterVRButton.__proto__ || Object.getPrototypeOf(EnterVRButton)).call(this)); options = options || {}; options.color = options.color || 'rgb(80,168,252)'; options.background = options.background || false; options.disabledOpacity = options.disabledOpacity || 0.5; options.height = options.height || 55; options.corners = options.corners || 'square'; options.cssprefix = options.cssprefix || 'webvr-ui'; options.textEnterVRTitle = options.textEnterVRTitle || 'ENTER VR'; options.textVRNotFoundTitle = options.textVRNotFoundTitle || 'VR NOT FOUND'; options.textExitVRTitle = options.textExitVRTitle || 'EXIT VR'; options.onRequestStateChange = options.onRequestStateChange || function () { return true; }; options.beforeEnter = options.beforeEnter || function () { return new Promise(function (resolve) { return resolve(); }); }; options.beforeExit = options.beforeExit || function () { return new Promise(function (resolve) { return resolve(); }); }; options.injectCSS = options.injectCSS !== false; _this.options = options; _this.sourceCanvas = sourceCanvas; // Pass in your own domElement if you really dont want to use ours _this.domElement = options.domElement || (0, _dom.createDefaultView)(options); _this.__defaultDisplayStyle = _this.domElement.style.display || 'initial'; // Create WebVR Manager _this.manager = new _webvrManager2.default(); _this.manager.checkDisplays(); _this.manager.addListener('change', function (state) { return _this.__onStateChange(state); }); // Bind button click events to __onClick _this.domElement.addEventListener('click', function () { return _this.__onEnterVRClick(); }); _this.__forceDisabled = false; _this.setTitle(_this.options.textEnterVRTitle); return _this; } /** * Set the title of the button * @param {string} text * @return {EnterVRButton} */ _createClass(EnterVRButton, [{ key: 'setTitle', value: function setTitle(text) { this.domElement.title = text; ifChild(this.domElement, this.options.cssprefix, 'title', function (title) { if (!text) { title.style.display = 'none'; } else { title.innerText = text; title.style.display = 'initial'; } }); return this; } /** * Set the tooltip of the button * @param {string} tooltip * @return {EnterVRButton} */ }, { key: 'setTooltip', value: function setTooltip(tooltip) { this.domElement.title = tooltip; return this; } /** * Show the button * @return {EnterVRButton} */ }, { key: 'show', value: function show() { this.domElement.style.display = this.__defaultDisplayStyle; this.emit('show'); return this; } /** * Hide the button * @return {EnterVRButton} */ }, { key: 'hide', value: function hide() { this.domElement.style.display = 'none'; this.emit('hide'); return this; } /** * Enable the button * @return {EnterVRButton} */ }, { key: 'enable', value: function enable() { this.__setDisabledAttribute(false); this.__forceDisabled = false; return this; } /** * Disable the button from being clicked * @return {EnterVRButton} */ }, { key: 'disable', value: function disable() { this.__setDisabledAttribute(true); this.__forceDisabled = true; return this; } /** * clean up object for garbage collection */ }, { key: 'remove', value: function remove() { this.manager.remove(); if (this.domElement.parentElement) { this.domElement.parentElement.removeChild(this.domElement); } } /** * Returns a promise getting the VRDisplay used * @return {Promise.} */ }, { key: 'getVRDisplay', value: function getVRDisplay() { return _webvrManager2.default.getVRDisplay(); } /** * Check if the canvas the button is connected to is currently presenting * @return {boolean} */ }, { key: 'isPresenting', value: function isPresenting() { return this.state === _states2.default.PRESENTING || this.state == _states2.default.PRESENTING_FULLSCREEN; } /** * Request entering VR * @return {Promise} */ }, { key: 'requestEnterVR', value: function requestEnterVR() { var _this2 = this; return new Promise(function (resolve, reject) { if (_this2.options.onRequestStateChange(_states2.default.PRESENTING)) { return _this2.options.beforeEnter().then(function () { return _this2.manager.enterVR(_this2.manager.defaultDisplay, _this2.sourceCanvas); }).then(resolve); } else { reject(new Error(_states2.default.ERROR_REQUEST_STATE_CHANGE_REJECTED)); } }); } /** * Request exiting presentation mode * @return {Promise} */ }, { key: 'requestExit', value: function requestExit() { var _this3 = this; var initialState = this.state; return new Promise(function (resolve, reject) { if (_this3.options.onRequestStateChange(_states2.default.READY_TO_PRESENT)) { return _this3.options.beforeExit().then(function () { return ( // if we were presenting VR, exit VR, if we are // exiting fullscreen, exit fullscreen initialState === _states2.default.PRESENTING ? _this3.manager.exitVR(_this3.manager.defaultDisplay) : _this3.manager.exitFullscreen() ); }).then(resolve); } else { reject(new Error(_states2.default.ERROR_REQUEST_STATE_CHANGE_REJECTED)); } }); } /** * Request entering the site in fullscreen, but not VR * @return {Promise} */ }, { key: 'requestEnterFullscreen', value: function requestEnterFullscreen() { var _this4 = this; return new Promise(function (resolve, reject) { if (_this4.options.onRequestStateChange(_states2.default.PRESENTING_FULLSCREEN)) { return _this4.options.beforeEnter().then(function () { return _this4.manager.enterFullscreen(_this4.sourceCanvas); }).then(resolve); } else { reject(new Error(_states2.default.ERROR_REQUEST_STATE_CHANGE_REJECTED)); } }); } /** * Set the disabled attribute * @param {boolean} disabled * @private */ }, { key: '__setDisabledAttribute', value: function __setDisabledAttribute(disabled) { if (disabled || this.__forceDisabled) { this.domElement.setAttribute('disabled', 'true'); } else { this.domElement.removeAttribute('disabled'); } } /** * Handling click event from button * @private */ }, { key: '__onEnterVRClick', value: function __onEnterVRClick() { if (this.state == _states2.default.READY_TO_PRESENT) { this.requestEnterVR(); } else if (this.isPresenting()) { this.requestExit(); } } /** * @param {State} state the state that its transitioning to * @private */ }, { key: '__onStateChange', value: function __onStateChange(state) { if (state != this.state) { if (this.state === _states2.default.PRESENTING || this.state === _states2.default.PRESENTING_FULLSCREEN) { this.emit('exit'); } this.state = state; switch (state) { case _states2.default.READY_TO_PRESENT: this.show(); this.setTitle(this.options.textEnterVRTitle); if (this.manager.defaultDisplay) { this.setTooltip('Enter VR using ' + this.manager.defaultDisplay.displayName); } this.__setDisabledAttribute(false); this.emit('ready'); break; case _states2.default.PRESENTING: case _states2.default.PRESENTING_FULLSCREEN: if (!this.manager.defaultDisplay || !this.manager.defaultDisplay.capabilities.hasExternalDisplay || state == _states2.default.PRESENTING_FULLSCREEN) { this.hide(); } this.setTitle(this.options.textExitVRTitle); this.__setDisabledAttribute(false); this.emit('enter'); break; // Error states case _states2.default.ERROR_BROWSER_NOT_SUPPORTED: this.show(); this.setTitle(this.options.textVRNotFoundTitle); this.setTooltip('Browser not supported'); this.__setDisabledAttribute(true); this.emit('error', new Error(state)); break; case _states2.default.ERROR_NO_PRESENTABLE_DISPLAYS: this.show(); this.setTitle(this.options.textVRNotFoundTitle); this.setTooltip('No VR headset found.'); this.__setDisabledAttribute(true); this.emit('error', new Error(state)); break; case _states2.default.ERROR_REQUEST_TO_PRESENT_REJECTED: this.show(); this.setTitle(this.options.textVRNotFoundTitle); this.setTooltip('Something went wrong trying to start presenting to your headset.'); this.__setDisabledAttribute(true); this.emit('error', new Error(state)); break; case _states2.default.ERROR_EXIT_PRESENT_REJECTED: default: this.show(); this.setTitle(this.options.textVRNotFoundTitle); this.setTooltip('Unknown error.'); this.__setDisabledAttribute(true); this.emit('error', new Error(state)); } } } }]); return EnterVRButton; }(_eventemitter2.default); /** * Function checking if a specific css class exists as child of element. * * @param {HTMLElement} el element to find child in * @param {string} cssPrefix css prefix of button * @param {string} suffix class name * @param {function} fn function to call if child is found * @private */ exports.default = EnterVRButton; var ifChild = function ifChild(el, cssPrefix, suffix, fn) { var c = el.querySelector('.' + cssPrefix + '-' + suffix); c && fn(c); }; },{"./dom":4,"./states":7,"./webvr-manager":8,"eventemitter3":1}],6:[function(_dereq_,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.WebVRManager = exports.State = exports.dom = exports.EnterVRButton = undefined; var _webvrManager = _dereq_('./webvr-manager'); var _webvrManager2 = _interopRequireDefault(_webvrManager); var _states = _dereq_('./states'); var _states2 = _interopRequireDefault(_states); var _dom = _dereq_('./dom'); var dom = _interopRequireWildcard(_dom); var _enterVrButton = _dereq_('./enter-vr-button'); var _enterVrButton2 = _interopRequireDefault(_enterVrButton); _dereq_('./aframe-component'); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } exports.EnterVRButton = _enterVrButton2.default; exports.dom = dom; exports.State = _states2.default; exports.WebVRManager = _webvrManager2.default; // Copyright 2016 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. },{"./aframe-component":3,"./dom":4,"./enter-vr-button":5,"./states":7,"./webvr-manager":8}],7:[function(_dereq_,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); // Copyright 2016 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Not yet presenting, but ready to present var READY_TO_PRESENT = 'ready'; // In presentation mode var PRESENTING = 'presenting'; var PRESENTING_FULLSCREEN = 'presenting-fullscreen'; // Checking device availability var PREPARING = 'preparing'; // Errors var ERROR_NO_PRESENTABLE_DISPLAYS = 'error-no-presentable-displays'; var ERROR_BROWSER_NOT_SUPPORTED = 'error-browser-not-supported'; var ERROR_REQUEST_TO_PRESENT_REJECTED = 'error-request-to-present-rejected'; var ERROR_EXIT_PRESENT_REJECTED = 'error-exit-present-rejected'; var ERROR_REQUEST_STATE_CHANGE_REJECTED = 'error-request-state-change-rejected'; var ERROR_UNKOWN = 'error-unkown'; exports.default = { READY_TO_PRESENT: READY_TO_PRESENT, PRESENTING: PRESENTING, PRESENTING_FULLSCREEN: PRESENTING_FULLSCREEN, PREPARING: PREPARING, ERROR_NO_PRESENTABLE_DISPLAYS: ERROR_NO_PRESENTABLE_DISPLAYS, ERROR_BROWSER_NOT_SUPPORTED: ERROR_BROWSER_NOT_SUPPORTED, ERROR_REQUEST_TO_PRESENT_REJECTED: ERROR_REQUEST_TO_PRESENT_REJECTED, ERROR_EXIT_PRESENT_REJECTED: ERROR_EXIT_PRESENT_REJECTED, ERROR_REQUEST_STATE_CHANGE_REJECTED: ERROR_REQUEST_STATE_CHANGE_REJECTED, ERROR_UNKOWN: ERROR_UNKOWN }; },{}],8:[function(_dereq_,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); 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; }; }(); var _states = _dereq_('./states'); var _states2 = _interopRequireDefault(_states); var _eventemitter = _dereq_('eventemitter3'); var _eventemitter2 = _interopRequireDefault(_eventemitter); var _screenfull = _dereq_('screenfull'); var _screenfull2 = _interopRequireDefault(_screenfull); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } // Copyright 2016 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. /** * WebVR Manager is a utility to handle VR displays */ var WebVRManager = function (_EventEmitter) { _inherits(WebVRManager, _EventEmitter); /** * Construct a new WebVRManager */ function WebVRManager() { _classCallCheck(this, WebVRManager); var _this = _possibleConstructorReturn(this, (WebVRManager.__proto__ || Object.getPrototypeOf(WebVRManager)).call(this)); _this.state = _states2.default.PREPARING; // Bind vr display present change event to __onVRDisplayPresentChange _this.__onVRDisplayPresentChange = _this.__onVRDisplayPresentChange.bind(_this); window.addEventListener('vrdisplaypresentchange', _this.__onVRDisplayPresentChange); _this.__onChangeFullscreen = _this.__onChangeFullscreen.bind(_this); if (_screenfull2.default.enabled) { document.addEventListener(_screenfull2.default.raw.fullscreenchange, _this.__onChangeFullscreen); } return _this; } /** * Check if the browser is compatible with WebVR and has headsets. * @return {Promise} */ _createClass(WebVRManager, [{ key: 'checkDisplays', value: function checkDisplays() { var _this2 = this; return WebVRManager.getVRDisplay().then(function (display) { _this2.defaultDisplay = display; _this2.__setState(_states2.default.READY_TO_PRESENT); return display; }).catch(function (e) { delete _this2.defaultDisplay; if (e.name == 'NO_DISPLAYS') { _this2.__setState(_states2.default.ERROR_NO_PRESENTABLE_DISPLAYS); } else if (e.name == 'WEBVR_UNSUPPORTED') { _this2.__setState(_states2.default.ERROR_BROWSER_NOT_SUPPORTED); } else { _this2.__setState(_states2.default.ERROR_UNKOWN); } }); } /** * clean up object for garbage collection */ }, { key: 'remove', value: function remove() { window.removeEventListener('vrdisplaypresentchange', this.__onVRDisplayPresentChange); if (_screenfull2.default.enabled) { document.removeEventListener(_screenfull2.default.raw.fullscreenchanged, this.__onChangeFullscreen); } this.removeAllListeners(); } /** * returns promise returning list of available VR displays. * @return {Promise} */ }, { key: 'enterVR', /** * Enter presentation mode with your set VR display * @param {VRDisplay} display the display to request present on * @param {HTMLCanvasElement} canvas * @return {Promise.} */ value: function enterVR(display, canvas) { var _this3 = this; this.presentedSource = canvas; return display.requestPresent([{ source: canvas }]).then(function () {}, // this could fail if: // 1. Display `canPresent` is false // 2. Canvas is invalid // 3. not executed via user interaction function () { return _this3.__setState(_states2.default.ERROR_REQUEST_TO_PRESENT_REJECTED); }); } /** * Exit presentation mode on display * @param {VRDisplay} display * @return {Promise.} */ }, { key: 'exitVR', value: function exitVR(display) { var _this4 = this; return display.exitPresent().then(function () { _this4.presentedSource = undefined; }, // this could fail if: // 1. exit requested while not currently presenting function () { return _this4.__setState(_states2.default.ERROR_EXIT_PRESENT_REJECTED); }); } /** * Enter fullscreen mode * @param {HTMLCanvasElement} canvas * @return {boolean} */ }, { key: 'enterFullscreen', value: function enterFullscreen(canvas) { if (_screenfull2.default.enabled) { _screenfull2.default.request(canvas); } else { // iOS this.__setState(_states2.default.PRESENTING_FULLSCREEN); } return true; } /** * Exit fullscreen mode * @return {boolean} */ }, { key: 'exitFullscreen', value: function exitFullscreen() { if (_screenfull2.default.enabled && _screenfull2.default.isFullscreen) { _screenfull2.default.exit(); } else if (this.state == _states2.default.PRESENTING_FULLSCREEN) { this.checkDisplays(); } return true; } /** * Change the state of the manager * @param {State} state * @private */ }, { key: '__setState', value: function __setState(state) { if (state != this.state) { this.emit('change', state, this.state); this.state = state; } } /** * Triggered on fullscreen change event * @param {Event} e * @private */ }, { key: '__onChangeFullscreen', value: function __onChangeFullscreen(e) { if (_screenfull2.default.isFullscreen) { this.__setState(_states2.default.PRESENTING_FULLSCREEN); } else { this.checkDisplays(); } } /** * Triggered on vr present change * @param {Event} event * @private */ }, { key: '__onVRDisplayPresentChange', value: function __onVRDisplayPresentChange(event) { try { // Polyfill stores display under detail var display = event.display ? event.display : event.detail.display; if (display.isPresenting && display.getLayers()[0].source !== this.presentedSource) { // this means a different instance of WebVRManager has requested to present return; } var isPresenting = this.defaultDisplay && this.defaultDisplay.isPresenting; this.__setState(isPresenting ? _states2.default.PRESENTING : _states2.default.READY_TO_PRESENT); } catch (err) { // continue regardless of error } } }], [{ key: 'getVRDisplay', value: function getVRDisplay() { return new Promise(function (resolve, reject) { if (!navigator || !navigator.getVRDisplays) { var e = new Error('Browser not supporting WebVR'); e.name = 'WEBVR_UNSUPPORTED'; reject(e); return; } var rejectNoDisplay = function rejectNoDisplay() { // No displays are found. var e = new Error('No displays found'); e.name = 'NO_DISPLAYS'; reject(e); }; navigator.getVRDisplays().then(function (displays) { // Promise succeeds, but check if there are any displays actually. for (var i = 0; i < displays.length; i++) { if (displays[i].capabilities.canPresent) { resolve(displays[i]); break; } } rejectNoDisplay(); }, rejectNoDisplay); }); } }]); return WebVRManager; }(_eventemitter2.default); exports.default = WebVRManager; },{"./states":7,"eventemitter3":1,"screenfull":2}]},{},[6])(6) });