arcRotateCameraKeyboardMoveInput.ts 8.9 KB

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