freeCameraGamepadInput.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. import { __decorate } from "../../tslib.es6.js";
  2. import { serialize } from "../../Misc/decorators.js";
  3. import { CameraInputTypes } from "../../Cameras/cameraInputsManager.js";
  4. import { Matrix, Vector3, Vector2 } from "../../Maths/math.vector.js";
  5. import { Gamepad } from "../../Gamepads/gamepad.js";
  6. /**
  7. * Manage the gamepad inputs to control a free camera.
  8. * @see https://doc.babylonjs.com/features/featuresDeepDive/cameras/customizingCameraInputs
  9. */
  10. export class FreeCameraGamepadInput {
  11. constructor() {
  12. /**
  13. * Defines the gamepad rotation sensibility.
  14. * This is the threshold from when rotation starts to be accounted for to prevent jittering.
  15. */
  16. this.gamepadAngularSensibility = 200;
  17. /**
  18. * Defines the gamepad move sensibility.
  19. * This is the threshold from when moving starts to be accounted for for to prevent jittering.
  20. */
  21. this.gamepadMoveSensibility = 40;
  22. /**
  23. * Defines the minimum value at which any analog stick input is ignored.
  24. * Note: This value should only be a value between 0 and 1.
  25. */
  26. this.deadzoneDelta = 0.1;
  27. this._yAxisScale = 1.0;
  28. this._cameraTransform = Matrix.Identity();
  29. this._deltaTransform = Vector3.Zero();
  30. this._vector3 = Vector3.Zero();
  31. this._vector2 = Vector2.Zero();
  32. }
  33. /**
  34. * Gets or sets a boolean indicating that Yaxis (for right stick) should be inverted
  35. */
  36. get invertYAxis() {
  37. return this._yAxisScale !== 1.0;
  38. }
  39. set invertYAxis(value) {
  40. this._yAxisScale = value ? -1.0 : 1.0;
  41. }
  42. /**
  43. * Attach the input controls to a specific dom element to get the input from.
  44. */
  45. attachControl() {
  46. const manager = this.camera.getScene().gamepadManager;
  47. this._onGamepadConnectedObserver = manager.onGamepadConnectedObservable.add((gamepad) => {
  48. if (gamepad.type !== Gamepad.POSE_ENABLED) {
  49. // prioritize XBOX gamepads.
  50. if (!this.gamepad || gamepad.type === Gamepad.XBOX) {
  51. this.gamepad = gamepad;
  52. }
  53. }
  54. });
  55. this._onGamepadDisconnectedObserver = manager.onGamepadDisconnectedObservable.add((gamepad) => {
  56. if (this.gamepad === gamepad) {
  57. this.gamepad = null;
  58. }
  59. });
  60. // check if there are already other controllers connected
  61. this.gamepad = manager.getGamepadByType(Gamepad.XBOX);
  62. // if no xbox controller was found, but there are gamepad controllers, take the first one
  63. if (!this.gamepad && manager.gamepads.length) {
  64. this.gamepad = manager.gamepads[0];
  65. }
  66. }
  67. /**
  68. * Detach the current controls from the specified dom element.
  69. */
  70. detachControl() {
  71. this.camera.getScene().gamepadManager.onGamepadConnectedObservable.remove(this._onGamepadConnectedObserver);
  72. this.camera.getScene().gamepadManager.onGamepadDisconnectedObservable.remove(this._onGamepadDisconnectedObserver);
  73. this.gamepad = null;
  74. }
  75. /**
  76. * Update the current camera state depending on the inputs that have been used this frame.
  77. * This is a dynamically created lambda to avoid the performance penalty of looping for inputs in the render loop.
  78. */
  79. checkInputs() {
  80. if (this.gamepad && this.gamepad.leftStick) {
  81. const camera = this.camera;
  82. const lsValues = this.gamepad.leftStick;
  83. if (this.gamepadMoveSensibility !== 0) {
  84. lsValues.x = Math.abs(lsValues.x) > this.deadzoneDelta ? lsValues.x / this.gamepadMoveSensibility : 0;
  85. lsValues.y = Math.abs(lsValues.y) > this.deadzoneDelta ? lsValues.y / this.gamepadMoveSensibility : 0;
  86. }
  87. let rsValues = this.gamepad.rightStick;
  88. if (rsValues && this.gamepadAngularSensibility !== 0) {
  89. rsValues.x = Math.abs(rsValues.x) > this.deadzoneDelta ? rsValues.x / this.gamepadAngularSensibility : 0;
  90. rsValues.y = (Math.abs(rsValues.y) > this.deadzoneDelta ? rsValues.y / this.gamepadAngularSensibility : 0) * this._yAxisScale;
  91. }
  92. else {
  93. rsValues = { x: 0, y: 0 };
  94. }
  95. if (!camera.rotationQuaternion) {
  96. Matrix.RotationYawPitchRollToRef(camera.rotation.y, camera.rotation.x, 0, this._cameraTransform);
  97. }
  98. else {
  99. camera.rotationQuaternion.toRotationMatrix(this._cameraTransform);
  100. }
  101. const speed = camera._computeLocalCameraSpeed() * 50.0;
  102. this._vector3.copyFromFloats(lsValues.x * speed, 0, -lsValues.y * speed);
  103. Vector3.TransformCoordinatesToRef(this._vector3, this._cameraTransform, this._deltaTransform);
  104. camera.cameraDirection.addInPlace(this._deltaTransform);
  105. this._vector2.copyFromFloats(rsValues.y, rsValues.x);
  106. camera.cameraRotation.addInPlace(this._vector2);
  107. }
  108. }
  109. /**
  110. * Gets the class name of the current input.
  111. * @returns the class name
  112. */
  113. getClassName() {
  114. return "FreeCameraGamepadInput";
  115. }
  116. /**
  117. * Get the friendly name associated with the input class.
  118. * @returns the input friendly name
  119. */
  120. getSimpleName() {
  121. return "gamepad";
  122. }
  123. }
  124. __decorate([
  125. serialize()
  126. ], FreeCameraGamepadInput.prototype, "gamepadAngularSensibility", void 0);
  127. __decorate([
  128. serialize()
  129. ], FreeCameraGamepadInput.prototype, "gamepadMoveSensibility", void 0);
  130. CameraInputTypes["FreeCameraGamepadInput"] = FreeCameraGamepadInput;
  131. //# sourceMappingURL=freeCameraGamepadInput.js.map