arcRotateCameraVRDeviceOrientationInput.ts 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. import { ArcRotateCamera } from "../../Cameras/arcRotateCamera";
  2. import { ICameraInput, CameraInputTypes } from "../../Cameras/cameraInputsManager";
  3. import { ArcRotateCameraInputsManager } from "../../Cameras/arcRotateCameraInputsManager";
  4. import { Tools } from '../../Misc/tools';
  5. // Module augmentation to abstract orientation inputs from camera.
  6. declare module "../../Cameras/arcRotateCameraInputsManager" {
  7. export interface ArcRotateCameraInputsManager {
  8. /**
  9. * Add orientation input support to the input manager.
  10. * @returns the current input manager
  11. */
  12. addVRDeviceOrientation(): ArcRotateCameraInputsManager;
  13. }
  14. }
  15. /**
  16. * Add orientation input support to the input manager.
  17. * @returns the current input manager
  18. */
  19. ArcRotateCameraInputsManager.prototype.addVRDeviceOrientation = function(): ArcRotateCameraInputsManager {
  20. this.add(new ArcRotateCameraVRDeviceOrientationInput());
  21. return this;
  22. };
  23. /**
  24. * Manage the device orientation inputs (gyroscope) to control an arc rotate camera.
  25. * @see https://doc.babylonjs.com/how_to/customizing_camera_inputs
  26. */
  27. export class ArcRotateCameraVRDeviceOrientationInput implements ICameraInput<ArcRotateCamera> {
  28. /**
  29. * Defines the camera the input is attached to.
  30. */
  31. public camera: ArcRotateCamera;
  32. /**
  33. * Defines a correction factor applied on the alpha value retrieved from the orientation events.
  34. */
  35. public alphaCorrection = 1;
  36. /**
  37. * Defines a correction factor applied on the gamma value retrieved from the orientation events.
  38. */
  39. public gammaCorrection = 1;
  40. private _alpha = 0;
  41. private _gamma = 0;
  42. private _dirty = false;
  43. private _deviceOrientationHandler: () => void;
  44. /**
  45. * Instantiate a new ArcRotateCameraVRDeviceOrientationInput.
  46. */
  47. constructor() {
  48. this._deviceOrientationHandler = this._onOrientationEvent.bind(this);
  49. }
  50. /**
  51. * Attach the input controls to a specific dom element to get the input from.
  52. * @param noPreventDefault Defines whether event caught by the controls should call preventdefault() (https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault)
  53. */
  54. public attachControl(noPreventDefault?: boolean): void {
  55. noPreventDefault = Tools.BackCompatCameraNoPreventDefault(arguments);
  56. this.camera.attachControl(noPreventDefault);
  57. let hostWindow = this.camera.getScene().getEngine().getHostWindow();
  58. if (hostWindow) {
  59. // check iOS 13+ support
  60. if (typeof(DeviceOrientationEvent) !== "undefined" && typeof (<any>DeviceOrientationEvent).requestPermission === 'function') {
  61. (<any>DeviceOrientationEvent).requestPermission()
  62. .then((response: string) => {
  63. if (response === 'granted') {
  64. hostWindow!.addEventListener("deviceorientation", this._deviceOrientationHandler);
  65. } else {
  66. Tools.Warn("Permission not granted.");
  67. }
  68. })
  69. .catch((error: any) => {
  70. Tools.Error(error);
  71. });
  72. } else {
  73. hostWindow.addEventListener("deviceorientation", this._deviceOrientationHandler);
  74. }
  75. }
  76. }
  77. /** @hidden */
  78. public _onOrientationEvent(evt: DeviceOrientationEvent): void {
  79. if (evt.alpha !== null) {
  80. this._alpha = (+evt.alpha | 0) * this.alphaCorrection;
  81. }
  82. if (evt.gamma !== null) {
  83. this._gamma = (+evt.gamma | 0) * this.gammaCorrection;
  84. }
  85. this._dirty = true;
  86. }
  87. /**
  88. * Update the current camera state depending on the inputs that have been used this frame.
  89. * This is a dynamically created lambda to avoid the performance penalty of looping for inputs in the render loop.
  90. */
  91. public checkInputs(): void {
  92. if (this._dirty) {
  93. this._dirty = false;
  94. if (this._gamma < 0) {
  95. this._gamma = 180 + this._gamma;
  96. }
  97. this.camera.alpha = (-this._alpha / 180.0 * Math.PI) % Math.PI * 2;
  98. this.camera.beta = (this._gamma / 180.0 * Math.PI);
  99. }
  100. }
  101. /**
  102. * Detach the current controls from the specified dom element.
  103. */
  104. public detachControl(): void {
  105. window.removeEventListener("deviceorientation", this._deviceOrientationHandler);
  106. }
  107. /**
  108. * Gets the class name of the current intput.
  109. * @returns the class name
  110. */
  111. public getClassName(): string {
  112. return "ArcRotateCameraVRDeviceOrientationInput";
  113. }
  114. /**
  115. * Get the friendly name associated with the input class.
  116. * @returns the input friendly name
  117. */
  118. public getSimpleName(): string {
  119. return "VRDeviceOrientation";
  120. }
  121. }
  122. (<any>CameraInputTypes)["ArcRotateCameraVRDeviceOrientationInput"] = ArcRotateCameraVRDeviceOrientationInput;