UNPKG

aframe-extras

Version:

Add-ons and examples for A-Frame VR.

163 lines (135 loc) 4.97 kB
/* global AFRAME, THREE */ /* eslint-disable no-prototype-builtins */ import '../../lib/keyboard.polyfill.js'; const PROXY_FLAG = '__keyboard-controls-proxy'; const KeyboardEvent = window.KeyboardEvent; /** * Keyboard Controls component. * * Stripped-down version of: https://github.com/donmccurdy/aframe-keyboard-controls * * Bind keyboard events to components, or control your entities with the WASD keys. * * Why use KeyboardEvent.code? "This is set to a string representing the key that was pressed to * generate the KeyboardEvent, without taking the current keyboard layout (e.g., QWERTY vs. * Dvorak), locale (e.g., English vs. French), or any modifier keys into account. This is useful * when you care about which physical key was pressed, rather thanwhich character it corresponds * to. For example, if you’re a writing a game, you might want a certain set of keys to move the * player in different directions, and that mapping should ideally be independent of keyboard * layout. See: https://developers.google.com/web/updates/2016/04/keyboardevent-keys-codes * * @namespace wasd-controls * keys the entity moves and if you release it will stop. Easing simulates friction. * to the entity when pressing the keys. * @param {bool} [enabled=true] - To completely enable or disable the controls */ AFRAME.registerComponent('keyboard-controls', { schema: { enabled: { default: true }, debug: { default: false } }, init: function () { this.dVelocity = new THREE.Vector3(); this.localKeys = {}; this.listeners = { keydown: this.onKeyDown.bind(this), keyup: this.onKeyUp.bind(this), blur: this.onBlur.bind(this), onContextMenu: this.onContextMenu.bind(this), }; }, /******************************************************************* * Movement */ isVelocityActive: function () { return this.data.enabled && !!Object.keys(this.getKeys()).length; }, getVelocityDelta: function () { const data = this.data; const keys = this.getKeys(); this.dVelocity.set(0, 0, 0); if (data.enabled) { if (keys.KeyW || keys.ArrowUp) { this.dVelocity.z -= 1; } if (keys.KeyA || keys.ArrowLeft) { this.dVelocity.x -= 1; } if (keys.KeyS || keys.ArrowDown) { this.dVelocity.z += 1; } if (keys.KeyD || keys.ArrowRight) { this.dVelocity.x += 1; } // Move faster when the shift key is down. if (keys.ShiftLeft) { this.dVelocity = this.dVelocity.multiplyScalar(2); } } return this.dVelocity.clone(); }, /******************************************************************* * Events */ play: function () { this.attachEventListeners(); }, pause: function () { this.removeEventListeners(); }, attachEventListeners: function () { window.addEventListener("contextmenu", this.listeners.onContextMenu, false); window.addEventListener("keydown", this.listeners.keydown, false); window.addEventListener("keyup", this.listeners.keyup, false); window.addEventListener("blur", this.listeners.blur, false); }, onContextMenu: function () { for (const code in this.localKeys) { if (this.localKeys.hasOwnProperty(code)) { delete this.localKeys[code]; } } }, removeEventListeners: function () { window.removeEventListener('keydown', this.listeners.keydown); window.removeEventListener('keyup', this.listeners.keyup); window.removeEventListener('blur', this.listeners.blur); }, onKeyDown: function (event) { if (AFRAME.utils.shouldCaptureKeyEvent(event)) { this.localKeys[event.code] = true; this.emit(event); } }, onKeyUp: function (event) { if (AFRAME.utils.shouldCaptureKeyEvent(event)) { delete this.localKeys[event.code]; this.emit(event); } }, onBlur: function () { for (const code in this.localKeys) { if (this.localKeys.hasOwnProperty(code)) { delete this.localKeys[code]; } } }, emit: function (event) { // TODO - keydown only initially? // TODO - where the f is the spacebar // Emit original event. if (PROXY_FLAG in event) { // TODO - Method never triggered. this.el.emit(event.type, event); } // Emit convenience event, identifying key. this.el.emit(event.type + ':' + event.code, new KeyboardEvent(event.type, event)); if (this.data.debug) console.log(event.type + ':' + event.code); }, /******************************************************************* * Accessors */ isPressed: function (code) { return code in this.getKeys(); }, getKeys: function () { if (this.isProxied()) { return this.el.sceneEl.components['proxy-controls'].getKeyboard(); } return this.localKeys; }, isProxied: function () { const proxyControls = this.el.sceneEl.components['proxy-controls']; return proxyControls && proxyControls.isConnected(); } });