UNPKG

@babylonjs/core

Version:

Getting started? Play directly with the Babylon.js API using our [playground](https://playground.babylonjs.com/). It also contains a lot of samples to learn how to use it.

227 lines 10.2 kB
import { __decorate } from "../../tslib.es6.js"; import { serialize } from "../../Misc/decorators.js"; import { CameraInputTypes } from "../cameraInputsManager.js"; import { KeyboardEventTypes } from "../../Events/keyboardEvents.js"; import { Tools } from "../../Misc/tools.js"; /** * Manage the keyboard inputs to control the movement of a geospatial camera. * Arrow keys + Modifier key (ctrl/alt/option on mac): rotate * Arrow keys alone: pan * + / - keys: zoom in/out * @see https://doc.babylonjs.com/features/featuresDeepDive/cameras/customizingCameraInputs */ export class GeospatialCameraKeyboardInput { constructor() { /** * Defines the list of key codes associated with the up action (pan up) */ this.keysUp = [38]; /** * Defines the list of key codes associated with the down action (pan down) */ this.keysDown = [40]; /** * Defines the list of key codes associated with the left action (pan left) */ this.keysLeft = [37]; /** * Defines the list of key codes associated with the right action (pan right) */ this.keysRight = [39]; /** * Defines the list of key codes associated with zoom in (+ or =) */ this.keysZoomIn = [187, 107]; // 187 = + key, 107 = numpad + /** * Defines the list of key codes associated with zoom out (-) */ this.keysZoomOut = [189, 109]; // 189 = - key, 109 = numpad - /** * Defines the rotation sensitivity of the inputs. * (How many pixels of pointer input to apply per keypress, before rotation speed factor is applied by movement class) */ this.rotationSensitivity = 1.0; /** * Defines the panning sensitivity of the inputs. * (How many pixels of pointer input to apply per keypress, before pan speed factor is applied by movement class) */ this.panSensitivity = 1.0; /** * Defines the zooming sensitivity of the inputs. * (How many pixels of pointer input to apply per keypress, before zoom speed factor is applied by movement class) */ this.zoomSensitivity = 1.0; this._keys = new Array(); } /** * Attach the input controls to a specific dom element to get the input from. * @param noPreventDefault Defines whether event caught by the controls should call preventdefault() (https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault) */ attachControl(noPreventDefault) { // was there a second variable defined? noPreventDefault = Tools.BackCompatCameraNoPreventDefault(arguments); if (this._onCanvasBlurObserver) { return; } this._scene = this.camera.getScene(); this._engine = this._scene.getEngine(); this._onCanvasBlurObserver = this._engine.onCanvasBlurObservable.add(() => { this._keys.length = 0; }); this._onKeyboardObserver = this._scene.onKeyboardObservable.add((info) => { const evt = info.event; if (!evt.metaKey) { if (info.type === KeyboardEventTypes.KEYDOWN) { this._modifierPressed = evt.ctrlKey || evt.altKey; 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.keysZoomIn.indexOf(evt.keyCode) !== -1 || this.keysZoomOut.indexOf(evt.keyCode) !== -1) { const index = this._keys.indexOf(evt.keyCode); if (index === -1) { this._keys.push(evt.keyCode); } if (evt.preventDefault) { if (!noPreventDefault) { evt.preventDefault(); } } } } else { 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.keysZoomIn.indexOf(evt.keyCode) !== -1 || this.keysZoomOut.indexOf(evt.keyCode) !== -1) { const index = this._keys.indexOf(evt.keyCode); if (index >= 0) { this._keys.splice(index, 1); } if (evt.preventDefault) { if (!noPreventDefault) { evt.preventDefault(); } } } } } }); } /** * Detach the current controls from the specified dom element. */ detachControl() { if (this._scene) { this._onKeyboardObserver?.remove(); this._onKeyboardObserver = null; this._onCanvasBlurObserver?.remove(); this._onCanvasBlurObserver = null; } this._keys.length = 0; } /** * Update the current camera state depending on the inputs that have been used this frame. * This is a dynamically created lambda to avoid the performance penalty of looping for inputs in the render loop. */ checkInputs() { if (this._onKeyboardObserver) { const camera = this.camera; for (let index = 0; index < this._keys.length; index++) { const keyCode = this._keys[index]; if (this._modifierPressed) { // Rotation if (this.keysLeft.indexOf(keyCode) !== -1) { camera.movement.rotationAccumulatedPixels.y -= this.rotationSensitivity; } else if (this.keysRight.indexOf(keyCode) !== -1) { camera.movement.rotationAccumulatedPixels.y += this.rotationSensitivity; } else if (this.keysUp.indexOf(keyCode) !== -1) { camera.movement.rotationAccumulatedPixels.x -= this.rotationSensitivity; } else if (this.keysDown.indexOf(keyCode) !== -1) { camera.movement.rotationAccumulatedPixels.x += this.rotationSensitivity; } } else { // Zoom if (this.keysZoomIn.indexOf(keyCode) !== -1) { camera.movement.handleZoom(this.zoomSensitivity, false); } else if (this.keysZoomOut.indexOf(keyCode) !== -1) { camera.movement.handleZoom(-this.zoomSensitivity, false); } else { // Call into movement class handleDrag so that behavior matches that of pointer input, simulating drag from center of screen. // getRenderWidth/Height return render buffer pixels (scaled by hardwareScalingLevel relative to CSS pixels), // but the picking logic (scene.pick via CreatePickingRayToRef) expects CSS pixels (it divides by hardwareScalingLevel internally). const hardwareScaling = this._engine.getHardwareScalingLevel(); const centerX = (this._engine.getRenderWidth() / 2) * hardwareScaling; const centerY = (this._engine.getRenderHeight() / 2) * hardwareScaling; camera.movement.startDrag(centerX, centerY); if (this.keysLeft.indexOf(keyCode) !== -1) { camera.movement.handleDrag(centerX + this.panSensitivity, centerY); } else if (this.keysRight.indexOf(keyCode) !== -1) { camera.movement.handleDrag(centerX - this.panSensitivity, centerY); } else if (this.keysUp.indexOf(keyCode) !== -1) { camera.movement.handleDrag(centerX, centerY + this.panSensitivity); } else if (this.keysDown.indexOf(keyCode) !== -1) { camera.movement.handleDrag(centerX, centerY - this.panSensitivity); } camera.movement.stopDrag(); } } } } } /** * Gets the class name of the current input. * @returns the class name */ getClassName() { return "GeospatialCameraKeyboardInput"; } /** * Get the friendly name associated with the input class. * @returns the input friendly name */ getSimpleName() { return "keyboard"; } } __decorate([ serialize() ], GeospatialCameraKeyboardInput.prototype, "keysUp", void 0); __decorate([ serialize() ], GeospatialCameraKeyboardInput.prototype, "keysDown", void 0); __decorate([ serialize() ], GeospatialCameraKeyboardInput.prototype, "keysLeft", void 0); __decorate([ serialize() ], GeospatialCameraKeyboardInput.prototype, "keysRight", void 0); __decorate([ serialize() ], GeospatialCameraKeyboardInput.prototype, "keysZoomIn", void 0); __decorate([ serialize() ], GeospatialCameraKeyboardInput.prototype, "keysZoomOut", void 0); __decorate([ serialize() ], GeospatialCameraKeyboardInput.prototype, "rotationSensitivity", void 0); __decorate([ serialize() ], GeospatialCameraKeyboardInput.prototype, "panSensitivity", void 0); __decorate([ serialize() ], GeospatialCameraKeyboardInput.prototype, "zoomSensitivity", void 0); CameraInputTypes["GeospatialCameraKeyboardInput"] = GeospatialCameraKeyboardInput; //# sourceMappingURL=geospatialCameraKeyboardInput.js.map