如何

自定义相机输入


如何自定义相机输入

一旦您调用相机的attachControl功能,每个Babylon.js相机都会自动为您处理输入。您可以使用detachControl函数撤消控件。大多数Babylon.js专家使用两步过程来激活和连接相机:

//First, set the scene's activeCamera... to be YOUR camera.
scene.activeCamera = myCamera;
// Then attach the activeCamera to the canvas.
//Parameters: canvas, noPreventDefault
scene.activeCamera.attachControl(canvas, true);

更简单的版本可能如下所示:

myCamera.attachControl(canvas);

默认情况下,noPreventDefault设置为false,这意味着在所有画布鼠标单击和触摸事件上自动调用preventDefault()。

Babylon.js v2.4引入了一种不同的方式来管理摄像机输入,以提供一种面向输入可组合性的方法。您现在可以使用输入管理器,并且每个输入都可以被视为特定于此摄像机系列的插件,以及给定的输入类型(鼠标,键盘,游戏手柄,设备方向等)。

使用输入管理器,您可以添加,删除,启用或禁用相机可用的任何输入。您还可以非常轻松地实现自己的输入机制或覆盖现有的输入机制。

例如,输入管理器可通过名为inputs的属性获得

var camera = new BABYLON.FreeCamera("sceneCamera", new BABYLON.Vector3(0, 1, -15), scene);
var inputManager = camera.inputs;

配置您的输入

大多数输入提供设置以自定义敏感度并使其适应您自己的场景。

每个输入都在管理器上提供了一个简短的名称。目标是在玩输入时提供友好的语法。

var camera = new BABYLON.FreeCamera("sceneCamera", new BABYLON.Vector3(0, 1, -15), scene);
camera.inputs.add(new BABYLON.FreeCameraGamepadInput());
camera.inputs.attached.gamepad.gamepadAngularSensibility = 250;

添加现有输入

ArcRotateCamera和FreeCamera的输入管理器都公开了用于添加内置输入的简写函数。

var camera = new BABYLON.FreeCamera("sceneCamera", new BABYLON.Vector3(0, 1, -15), scene);
camera.inputs.addGamepad();

如果您愿意,您还可以添加自己输入的实例(我们将在本文末尾介绍如何实现您自己的输入)。

var camera = new BABYLON.FreeCamera("sceneCamera", new BABYLON.Vector3(0, 1, -15), scene);
camera.inputs.add(new BABYLON.FreeCameraGamepadInput());

启用或禁用输入

当您在相机上调用“attachControl”时,您将激活连接到输入管理器的所有输入。以同样的方式,您可以通过在相机上调用“detachControl”来关闭所有输入。

如果要暂时禁用输入,可以直接在输入上调用“detachControl”...如下所示:

var camera = new BABYLON.FreeCamera("sceneCamera", new BABYLON.Vector3(0, 1, -15), scene);
camera.inputs.attached.mouse.detachControl();
camera.inputs.addGamepad();

然后,当您想再次打开它时,可以调用“attachInput”。

camera.inputs.attachInput(camera.inputs.attached.mouse);

删除输入

有时你需要一个非常具体的输入机制。在这种情况下,最好的方法可能是清除所有输入并仅添加场景中可能需要的输入。

var camera = new BABYLON.FreeCamera("sceneCamera", new BABYLON.Vector3(0, 1, -15), scene);
camera.inputs.clear();
camera.inputs.addMouse();

您还可以从输入管理器中删除单个输入。您可以按实例或类型名称删除它们

var camera = new BABYLON.FreeCamera("sceneCamera", new BABYLON.Vector3(0, 1, -15), scene);
//remove by instance
camera.inputs.remove(camera.inputs.attached.mouse);
//remove by type
camera.inputs.removeByType("FreeCameraKeyboardMoveInput");

实现自己的输入

您的输入法创建为函数对象。您必须为具有所需名称的多个方法编写代码,这些方法由输入函数对象调用。方法名称和目的是

//This function must return the type name of the camera, it could be used for serializing your scene
getTypeName();

//This function must return the simple name that will be injected in the input manager as short hand
//for example "mouse" will turn into camera.inputs.attached.mouse
getSimpleName();

//This function must activate your input event.  Even if your input does not need a DOM element
// element and noPreventDefault must be present and used as parameter names.
// Return void.
attachControl(element, noPreventDefault);

//Detach control must deactivate your input and release all pointers, closures or event listeners
//element must be present as a parameter name.
// Return void.
detachControl(element);        

//This optional function will get called for each rendered frame, if you want to synchronize your input to rendering,
//no need to use requestAnimationFrame. It's a good place for applying calculations if you have to.
// Return void.
checkInputs();

用Javascript

这改变了键的正常使用,使相机左右移动,前后移动到当前位置旋转。

首先删除默认键盘输入。

camera.inputs.removeByType("FreeCameraKeyboardMoveInput");

现在创建新的输入法FreeCameraKeyboardRotateInput

var FreeCameraKeyboardRotateInput = function () {
    this._keys = [];
    this.keysLeft = [37];
    this.keysRight = [39];
    this.sensibility = 0.01;
}

添加获取名称方法

FreeCameraKeyboardRotateInput.prototype.getTypeName = function () {
    return "FreeCameraKeyboardRotateInput";
};
FreeCameraKeyboardRotateInput.prototype.getSimpleName = function () {
    return "keyboardRotate";
};

和附着和分离方法

FreeCameraKeyboardRotateInput.prototype.attachControl = function (element, noPreventDefault) {
    var _this = this;
    if (!this._onKeyDown) {
        element.tabIndex = 1;
        this._onKeyDown = function (evt) {
            if (_this.keysLeft.indexOf(evt.keyCode) !== -1 ||
                _this.keysRight.indexOf(evt.keyCode) !== -1) {
                var index = _this._keys.indexOf(evt.keyCode);
                if (index === -1) {
                    _this._keys.push(evt.keyCode);
                }
                if (!noPreventDefault) {
                    evt.preventDefault();
                }
            }
        };
        this._onKeyUp = function (evt) {
            if (_this.keysLeft.indexOf(evt.keyCode) !== -1 ||
                 _this.keysRight.indexOf(evt.keyCode) !== -1) {
                var index = _this._keys.indexOf(evt.keyCode);
                if (index >= 0) {
                    _this._keys.splice(index, 1);
                }
                if (!noPreventDefault) {
                    evt.preventDefault();
                }
            }
        };

        element.addEventListener("keydown", this._onKeyDown, false);
        element.addEventListener("keyup", this._onKeyUp, false);
        BABYLON.Tools.RegisterTopRootEvents([
            { name: "blur", handler: this._onLostFocus }
        ]);
    }
};


FreeCameraKeyboardRotateInput.prototype.detachControl = function (element) {
    if (this._onKeyDown) {
        element.removeEventListener("keydown", this._onKeyDown);
        element.removeEventListener("keyup", this._onKeyUp);
        BABYLON.Tools.UnregisterTopRootEvents([
            { name: "blur", handler: this._onLostFocus }
        ]);
        this._keys = [];
        this._onKeyDown = null;
        this._onKeyUp = null;
    }
};

可选择添加检查输入

FreeCameraKeyboardRotateInput.prototype.checkInputs = function () {
    if (this._onKeyDown) {
        var camera = this.camera;
        // Keyboard
        for (var index = 0; index < this._keys.length; index++) {
            var keyCode = this._keys[index];
            if (this.keysLeft.indexOf(keyCode) !== -1) {
                camera.cameraRotation.y += this.sensibility;
            }
            else if (this.keysRight.indexOf(keyCode) !== -1) {
                camera.cameraRotation.y -= this.sensibility;
            }
        }
    }
};

最后将这种新的输入方法添加到相机输入

    camera.inputs.add(new FreeCameraKeyboardRotateInput());

使用Typescript

使用TypeScript,您可以实现接口ICameraInput。

interface ICameraInput<TCamera extends BABYLON.Camera> {       
    // the input manager will fill the parent camera
    camera: TCamera;        

    //this function must return the type name of the camera, it could be used for serializing your scene
    getTypeName(): string;

    //this function must return the simple name that will be injected in the input manager as short hand
    //for example "mouse" will turn into camera.inputs.attached.mouse
    getSimpleName(): string;

    //this function must activate your input, event if your input does not need a DOM element
    attachControl: (element: HTMLElement, noPreventDefault?: boolean) => void;

    //detach control must deactivate your input and release all pointers, closures or event listeners
    detachControl: (element: HTMLElement) => void;        

    //this optional function will get called for each rendered frame, if you want to synchronize your input to rendering,
    //no need to use requestAnimationFrame. It's a good place for applying calculations if you have to
    checkInputs?: () => void;
}