import defaultValue from "../../Core/defaultValue.js"; import defined from "../../Core/defined.js"; import destroyObject from "../../Core/destroyObject.js"; import DeveloperError from "../../Core/DeveloperError.js"; import EventHelper from "../../Core/EventHelper.js"; import Fullscreen from "../../Core/Fullscreen.js"; import OrthographicFrustum from "../../Core/OrthographicFrustum.js"; import knockout from "../../ThirdParty/knockout.js"; import NoSleep from "../../ThirdParty/nosleep.js"; import createCommand from "../createCommand.js"; import getElement from "../getElement.js"; function lockScreen(orientation) { let locked = false; const screen = window.screen; if (defined(screen)) { if (defined(screen.lockOrientation)) { locked = screen.lockOrientation(orientation); } else if (defined(screen.mozLockOrientation)) { locked = screen.mozLockOrientation(orientation); } else if (defined(screen.msLockOrientation)) { locked = screen.msLockOrientation(orientation); } else if (defined(screen.orientation && screen.orientation.lock)) { locked = screen.orientation.lock(orientation); } } return locked; } function unlockScreen() { const screen = window.screen; if (defined(screen)) { if (defined(screen.unlockOrientation)) { screen.unlockOrientation(); } else if (defined(screen.mozUnlockOrientation)) { screen.mozUnlockOrientation(); } else if (defined(screen.msUnlockOrientation)) { screen.msUnlockOrientation(); } else if (defined(screen.orientation && screen.orientation.unlock)) { screen.orientation.unlock(); } } } function toggleVR(viewModel, scene, isVRMode, isOrthographic) { if (isOrthographic()) { return; } if (isVRMode()) { scene.useWebVR = false; if (viewModel._locked) { unlockScreen(); viewModel._locked = false; } viewModel._noSleep.disable(); Fullscreen.exitFullscreen(); isVRMode(false); } else { if (!Fullscreen.fullscreen) { Fullscreen.requestFullscreen(viewModel._vrElement); } viewModel._noSleep.enable(); if (!viewModel._locked) { viewModel._locked = lockScreen("landscape"); } scene.useWebVR = true; isVRMode(true); } } /** * The view model for {@link VRButton}. * @alias VRButtonViewModel * @constructor * * @param {Scene} scene The scene. * @param {Element|String} [vrElement=document.body] The element or id to be placed into VR mode. */ function VRButtonViewModel(scene, vrElement) { //>>includeStart('debug', pragmas.debug); if (!defined(scene)) { throw new DeveloperError("scene is required."); } //>>includeEnd('debug'); const that = this; const isEnabled = knockout.observable(Fullscreen.enabled); const isVRMode = knockout.observable(false); /** * Gets whether or not VR mode is active. * * @type {Boolean} */ this.isVRMode = undefined; knockout.defineProperty(this, "isVRMode", { get: function () { return isVRMode(); }, }); /** * Gets or sets whether or not VR functionality should be enabled. * * @type {Boolean} * @see Fullscreen.enabled */ this.isVREnabled = undefined; knockout.defineProperty(this, "isVREnabled", { get: function () { return isEnabled(); }, set: function (value) { isEnabled(value && Fullscreen.enabled); }, }); /** * Gets the tooltip. This property is observable. * * @type {String} */ this.tooltip = undefined; knockout.defineProperty(this, "tooltip", function () { if (!isEnabled()) { return "VR mode is unavailable"; } return isVRMode() ? "Exit VR mode" : "Enter VR mode"; }); const isOrthographic = knockout.observable(false); this._isOrthographic = undefined; knockout.defineProperty(this, "_isOrthographic", { get: function () { return isOrthographic(); }, }); this._eventHelper = new EventHelper(); this._eventHelper.add(scene.preRender, function () { isOrthographic(scene.camera.frustum instanceof OrthographicFrustum); }); this._locked = false; this._noSleep = new NoSleep(); this._command = createCommand(function () { toggleVR(that, scene, isVRMode, isOrthographic); }, knockout.getObservable(this, "isVREnabled")); this._vrElement = defaultValue(getElement(vrElement), document.body); this._callback = function () { if (!Fullscreen.fullscreen && isVRMode()) { scene.useWebVR = false; if (that._locked) { unlockScreen(); that._locked = false; } that._noSleep.disable(); isVRMode(false); } }; document.addEventListener(Fullscreen.changeEventName, this._callback); } Object.defineProperties(VRButtonViewModel.prototype, { /** * Gets or sets the HTML element to place into VR mode when the * corresponding button is pressed. * @memberof VRButtonViewModel.prototype * * @type {Element} */ vrElement: { //TODO:@exception {DeveloperError} value must be a valid HTML Element. get: function () { return this._vrElement; }, set: function (value) { //>>includeStart('debug', pragmas.debug); if (!(value instanceof Element)) { throw new DeveloperError("value must be a valid Element."); } //>>includeEnd('debug'); this._vrElement = value; }, }, /** * Gets the Command to toggle VR mode. * @memberof VRButtonViewModel.prototype * * @type {Command} */ command: { get: function () { return this._command; }, }, }); /** * @returns {Boolean} true if the object has been destroyed, false otherwise. */ VRButtonViewModel.prototype.isDestroyed = function () { return false; }; /** * Destroys the view model. Should be called to * properly clean up the view model when it is no longer needed. */ VRButtonViewModel.prototype.destroy = function () { this._eventHelper.removeAll(); document.removeEventListener(Fullscreen.changeEventName, this._callback); destroyObject(this); }; export default VRButtonViewModel;