@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
JavaScript
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