VRButtonViewModel.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. import defaultValue from '../../Core/defaultValue.js';
  2. import defined from '../../Core/defined.js';
  3. import defineProperties from '../../Core/defineProperties.js';
  4. import destroyObject from '../../Core/destroyObject.js';
  5. import DeveloperError from '../../Core/DeveloperError.js';
  6. import EventHelper from '../../Core/EventHelper.js';
  7. import Fullscreen from '../../Core/Fullscreen.js';
  8. import OrthographicFrustum from '../../Core/OrthographicFrustum.js';
  9. import knockout from '../../ThirdParty/knockout.js';
  10. import NoSleep from '../../ThirdParty/NoSleep.js';
  11. import createCommand from '../createCommand.js';
  12. import getElement from '../getElement.js';
  13. function lockScreen(orientation) {
  14. var locked = false;
  15. var screen = window.screen;
  16. if (defined(screen)) {
  17. if (defined(screen.lockOrientation)) {
  18. locked = screen.lockOrientation(orientation);
  19. } else if (defined(screen.mozLockOrientation)) {
  20. locked = screen.mozLockOrientation(orientation);
  21. } else if (defined(screen.msLockOrientation)) {
  22. locked = screen.msLockOrientation(orientation);
  23. } else if (defined(screen.orientation && screen.orientation.lock)) {
  24. locked = screen.orientation.lock(orientation);
  25. }
  26. }
  27. return locked;
  28. }
  29. function unlockScreen() {
  30. var screen = window.screen;
  31. if (defined(screen)) {
  32. if (defined(screen.unlockOrientation)) {
  33. screen.unlockOrientation();
  34. } else if (defined(screen.mozUnlockOrientation)) {
  35. screen.mozUnlockOrientation();
  36. } else if (defined(screen.msUnlockOrientation)) {
  37. screen.msUnlockOrientation();
  38. } else if (defined(screen.orientation && screen.orientation.unlock)) {
  39. screen.orientation.unlock();
  40. }
  41. }
  42. }
  43. function toggleVR(viewModel, scene, isVRMode, isOrthographic) {
  44. if (isOrthographic()) {
  45. return;
  46. }
  47. if (isVRMode()) {
  48. scene.useWebVR = false;
  49. if (viewModel._locked) {
  50. unlockScreen();
  51. viewModel._locked = false;
  52. }
  53. viewModel._noSleep.disable();
  54. Fullscreen.exitFullscreen();
  55. isVRMode(false);
  56. } else {
  57. if (!Fullscreen.fullscreen) {
  58. Fullscreen.requestFullscreen(viewModel._vrElement);
  59. }
  60. viewModel._noSleep.enable();
  61. if (!viewModel._locked) {
  62. viewModel._locked = lockScreen('landscape');
  63. }
  64. scene.useWebVR = true;
  65. isVRMode(true);
  66. }
  67. }
  68. /**
  69. * The view model for {@link VRButton}.
  70. * @alias VRButtonViewModel
  71. * @constructor
  72. *
  73. * @param {Scene} scene The scene.
  74. * @param {Element|String} [vrElement=document.body] The element or id to be placed into VR mode.
  75. */
  76. function VRButtonViewModel(scene, vrElement) {
  77. //>>includeStart('debug', pragmas.debug);
  78. if (!defined(scene)) {
  79. throw new DeveloperError('scene is required.');
  80. }
  81. //>>includeEnd('debug');
  82. var that = this;
  83. var isEnabled = knockout.observable(Fullscreen.enabled);
  84. var isVRMode = knockout.observable(false);
  85. /**
  86. * Gets whether or not VR mode is active.
  87. *
  88. * @type {Boolean}
  89. */
  90. this.isVRMode = undefined;
  91. knockout.defineProperty(this, 'isVRMode', {
  92. get : function() {
  93. return isVRMode();
  94. }
  95. });
  96. /**
  97. * Gets or sets whether or not VR functionality should be enabled.
  98. *
  99. * @type {Boolean}
  100. * @see Fullscreen.enabled
  101. */
  102. this.isVREnabled = undefined;
  103. knockout.defineProperty(this, 'isVREnabled', {
  104. get : function() {
  105. return isEnabled();
  106. },
  107. set : function(value) {
  108. isEnabled(value && Fullscreen.enabled);
  109. }
  110. });
  111. /**
  112. * Gets the tooltip. This property is observable.
  113. *
  114. * @type {String}
  115. */
  116. this.tooltip = undefined;
  117. knockout.defineProperty(this, 'tooltip', function() {
  118. if (!isEnabled()) {
  119. return 'VR mode is unavailable';
  120. }
  121. return isVRMode() ? 'Exit VR mode' : 'Enter VR mode';
  122. });
  123. var isOrthographic = knockout.observable(false);
  124. this._isOrthographic = undefined;
  125. knockout.defineProperty(this, '_isOrthographic', {
  126. get : function() {
  127. return isOrthographic();
  128. }
  129. });
  130. this._eventHelper = new EventHelper();
  131. this._eventHelper.add(scene.preRender, function() {
  132. isOrthographic(scene.camera.frustum instanceof OrthographicFrustum);
  133. });
  134. this._locked = false;
  135. this._noSleep = new NoSleep();
  136. this._command = createCommand(function() {
  137. toggleVR(that, scene, isVRMode, isOrthographic);
  138. }, knockout.getObservable(this, 'isVREnabled'));
  139. this._vrElement = defaultValue(getElement(vrElement), document.body);
  140. this._callback = function() {
  141. if (!Fullscreen.fullscreen && isVRMode()) {
  142. scene.useWebVR = false;
  143. if (that._locked) {
  144. unlockScreen();
  145. that._locked = false;
  146. }
  147. that._noSleep.disable();
  148. isVRMode(false);
  149. }
  150. };
  151. document.addEventListener(Fullscreen.changeEventName, this._callback);
  152. }
  153. defineProperties(VRButtonViewModel.prototype, {
  154. /**
  155. * Gets or sets the HTML element to place into VR mode when the
  156. * corresponding button is pressed.
  157. * @memberof VRButtonViewModel.prototype
  158. *
  159. * @type {Element}
  160. */
  161. vrElement : {
  162. //TODO:@exception {DeveloperError} value must be a valid HTML Element.
  163. get : function() {
  164. return this._vrElement;
  165. },
  166. set : function(value) {
  167. //>>includeStart('debug', pragmas.debug);
  168. if (!(value instanceof Element)) {
  169. throw new DeveloperError('value must be a valid Element.');
  170. }
  171. //>>includeEnd('debug');
  172. this._vrElement = value;
  173. }
  174. },
  175. /**
  176. * Gets the Command to toggle VR mode.
  177. * @memberof VRButtonViewModel.prototype
  178. *
  179. * @type {Command}
  180. */
  181. command : {
  182. get : function() {
  183. return this._command;
  184. }
  185. }
  186. });
  187. /**
  188. * @returns {Boolean} true if the object has been destroyed, false otherwise.
  189. */
  190. VRButtonViewModel.prototype.isDestroyed = function() {
  191. return false;
  192. };
  193. /**
  194. * Destroys the view model. Should be called to
  195. * properly clean up the view model when it is no longer needed.
  196. */
  197. VRButtonViewModel.prototype.destroy = function() {
  198. this._eventHelper.removeAll();
  199. document.removeEventListener(Fullscreen.changeEventName, this._callback);
  200. destroyObject(this);
  201. };
  202. export default VRButtonViewModel;