arcRotateCameraKeyboardMoveInput.ts 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. import { Nullable } from "../../types";
  2. import { serialize } from "../../Misc/decorators";
  3. import { Observer } from "../../Misc/observable";
  4. import { Scene } from "../../scene";
  5. import { ArcRotateCamera } from "../../Cameras/arcRotateCamera";
  6. import { ICameraInput, CameraInputTypes } from "../../Cameras/cameraInputsManager";
  7. import { Engine } from "../../Engines/engine";
  8. import { KeyboardInfo, KeyboardEventTypes } from "../../Events/keyboardEvents";
  9. import { Tools } from '../../Misc/tools';
  10. /**
  11. * Manage the keyboard inputs to control the movement of an arc rotate camera.
  12. * @see https://doc.babylonjs.com/how_to/customizing_camera_inputs
  13. */
  14. export class ArcRotateCameraKeyboardMoveInput implements ICameraInput<ArcRotateCamera> {
  15. /**
  16. * Defines the camera the input is attached to.
  17. */
  18. public camera: ArcRotateCamera;
  19. /**
  20. * Defines the list of key codes associated with the up action (increase alpha)
  21. */
  22. @serialize()
  23. public keysUp = [38];
  24. /**
  25. * Defines the list of key codes associated with the down action (decrease alpha)
  26. */
  27. @serialize()
  28. public keysDown = [40];
  29. /**
  30. * Defines the list of key codes associated with the left action (increase beta)
  31. */
  32. @serialize()
  33. public keysLeft = [37];
  34. /**
  35. * Defines the list of key codes associated with the right action (decrease beta)
  36. */
  37. @serialize()
  38. public keysRight = [39];
  39. /**
  40. * Defines the list of key codes associated with the reset action.
  41. * Those keys reset the camera to its last stored state (with the method camera.storeState())
  42. */
  43. @serialize()
  44. public keysReset = [220];
  45. /**
  46. * Defines the panning sensibility of the inputs.
  47. * (How fast is the camera panning)
  48. */
  49. @serialize()
  50. public panningSensibility: number = 50.0;
  51. /**
  52. * Defines the zooming sensibility of the inputs.
  53. * (How fast is the camera zooming)
  54. */
  55. @serialize()
  56. public zoomingSensibility: number = 25.0;
  57. /**
  58. * Defines whether maintaining the alt key down switch the movement mode from
  59. * orientation to zoom.
  60. */
  61. @serialize()
  62. public useAltToZoom: boolean = true;
  63. /**
  64. * Rotation speed of the camera
  65. */
  66. @serialize()
  67. public angularSpeed = 0.01;
  68. private _keys = new Array<number>();
  69. private _ctrlPressed: boolean;
  70. private _altPressed: boolean;
  71. private _onCanvasBlurObserver: Nullable<Observer<Engine>>;
  72. private _onKeyboardObserver: Nullable<Observer<KeyboardInfo>>;
  73. private _engine: Engine;
  74. private _scene: Scene;
  75. /**
  76. * Attach the input controls to a specific dom element to get the input from.
  77. * @param noPreventDefault Defines whether event caught by the controls should call preventdefault() (https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault)
  78. */
  79. public attachControl(noPreventDefault?: boolean): void {
  80. // was there a second variable defined?
  81. noPreventDefault = Tools.BackCompatCameraNoPreventDefault(arguments);
  82. if (this._onCanvasBlurObserver) {
  83. return;
  84. }
  85. this._scene = this.camera.getScene();
  86. this._engine = this._scene.getEngine();
  87. this._onCanvasBlurObserver = this._engine.onCanvasBlurObservable.add(() => {
  88. this._keys = [];
  89. });
  90. this._onKeyboardObserver = this._scene.onKeyboardObservable.add((info) => {
  91. let evt = info.event;
  92. if (!evt.metaKey) {
  93. if (info.type === KeyboardEventTypes.KEYDOWN) {
  94. this._ctrlPressed = evt.ctrlKey;
  95. this._altPressed = evt.altKey;
  96. if (this.keysUp.indexOf(evt.keyCode) !== -1 || this.keysDown.indexOf(evt.keyCode) !== -1 || this.keysLeft.indexOf(evt.keyCode) !== -1 || this.keysRight.indexOf(evt.keyCode) !== -1 || this.keysReset.indexOf(evt.keyCode) !== -1) {
  97. var index = this._keys.indexOf(evt.keyCode);
  98. if (index === -1) {
  99. this._keys.push(evt.keyCode);
  100. }
  101. if (evt.preventDefault) {
  102. if (!noPreventDefault) {
  103. evt.preventDefault();
  104. }
  105. }
  106. }
  107. } else {
  108. if (this.keysUp.indexOf(evt.keyCode) !== -1 || this.keysDown.indexOf(evt.keyCode) !== -1 || this.keysLeft.indexOf(evt.keyCode) !== -1 || this.keysRight.indexOf(evt.keyCode) !== -1 || this.keysReset.indexOf(evt.keyCode) !== -1) {
  109. var index = this._keys.indexOf(evt.keyCode);
  110. if (index >= 0) {
  111. this._keys.splice(index, 1);
  112. }
  113. if (evt.preventDefault) {
  114. if (!noPreventDefault) {
  115. evt.preventDefault();
  116. }
  117. }
  118. }
  119. }
  120. }
  121. });
  122. }
  123. /**
  124. * Detach the current controls from the specified dom element.
  125. */
  126. public detachControl(): void;
  127. /**
  128. * Detach the current controls from the specified dom element.
  129. * @param ignored defines an ignored parameter kept for backward compatibility. If you want to define the source input element, you can set engine.inputElement before calling camera.attachControl
  130. */
  131. public detachControl(ignored?: any): void {
  132. if (this._scene) {
  133. if (this._onKeyboardObserver) {
  134. this._scene.onKeyboardObservable.remove(this._onKeyboardObserver);
  135. }
  136. if (this._onCanvasBlurObserver) {
  137. this._engine.onCanvasBlurObservable.remove(this._onCanvasBlurObserver);
  138. }
  139. this._onKeyboardObserver = null;
  140. this._onCanvasBlurObserver = null;
  141. }
  142. this._keys = [];
  143. }
  144. /**
  145. * Update the current camera state depending on the inputs that have been used this frame.
  146. * This is a dynamically created lambda to avoid the performance penalty of looping for inputs in the render loop.
  147. */
  148. public checkInputs(): void {
  149. if (this._onKeyboardObserver) {
  150. var camera = this.camera;
  151. for (var index = 0; index < this._keys.length; index++) {
  152. var keyCode = this._keys[index];
  153. if (this.keysLeft.indexOf(keyCode) !== -1) {
  154. if (this._ctrlPressed && this.camera._useCtrlForPanning) {
  155. camera.inertialPanningX -= 1 / this.panningSensibility;
  156. } else {
  157. camera.inertialAlphaOffset -= this.angularSpeed;
  158. }
  159. } else if (this.keysUp.indexOf(keyCode) !== -1) {
  160. if (this._ctrlPressed && this.camera._useCtrlForPanning) {
  161. camera.inertialPanningY += 1 / this.panningSensibility;
  162. } else if (this._altPressed && this.useAltToZoom) {
  163. camera.inertialRadiusOffset += 1 / this.zoomingSensibility;
  164. } else {
  165. camera.inertialBetaOffset -= this.angularSpeed;
  166. }
  167. } else if (this.keysRight.indexOf(keyCode) !== -1) {
  168. if (this._ctrlPressed && this.camera._useCtrlForPanning) {
  169. camera.inertialPanningX += 1 / this.panningSensibility;
  170. } else {
  171. camera.inertialAlphaOffset += this.angularSpeed;
  172. }
  173. } else if (this.keysDown.indexOf(keyCode) !== -1) {
  174. if (this._ctrlPressed && this.camera._useCtrlForPanning) {
  175. camera.inertialPanningY -= 1 / this.panningSensibility;
  176. } else if (this._altPressed && this.useAltToZoom) {
  177. camera.inertialRadiusOffset -= 1 / this.zoomingSensibility;
  178. } else {
  179. camera.inertialBetaOffset += this.angularSpeed;
  180. }
  181. } else if (this.keysReset.indexOf(keyCode) !== -1) {
  182. if (camera.useInputToRestoreState) {
  183. camera.restoreState();
  184. }
  185. }
  186. }
  187. }
  188. }
  189. /**
  190. * Gets the class name of the current intput.
  191. * @returns the class name
  192. */
  193. public getClassName(): string {
  194. return "ArcRotateCameraKeyboardMoveInput";
  195. }
  196. /**
  197. * Get the friendly name associated with the input class.
  198. * @returns the input friendly name
  199. */
  200. public getSimpleName(): string {
  201. return "keyboard";
  202. }
  203. }
  204. (<any>CameraInputTypes)["ArcRotateCameraKeyboardMoveInput"] = ArcRotateCameraKeyboardMoveInput;