playcanvas
Version:
PlayCanvas WebGL game engine
158 lines (155 loc) • 4.62 kB
JavaScript
import { EventHandler } from '../../core/event-handler.js';
import { KeyboardEvent } from './keyboard-event.js';
const _keyboardEvent = new KeyboardEvent();
function makeKeyboardEvent(event) {
_keyboardEvent.key = event.keyCode;
_keyboardEvent.element = event.target;
_keyboardEvent.event = event;
return _keyboardEvent;
}
function toKeyCode(s) {
if (typeof s === 'string') {
return s.toUpperCase().charCodeAt(0);
}
return s;
}
const _keyCodeToKeyIdentifier = {
'9': 'Tab',
'13': 'Enter',
'16': 'Shift',
'17': 'Control',
'18': 'Alt',
'27': 'Escape',
'37': 'Left',
'38': 'Up',
'39': 'Right',
'40': 'Down',
'46': 'Delete',
'91': 'Win'
};
class Keyboard extends EventHandler {
static{
this.EVENT_KEYDOWN = 'keydown';
}
static{
this.EVENT_KEYUP = 'keyup';
}
constructor(element, options = {}){
super(), this._element = null, this._keymap = {}, this._lastmap = {};
this._keyDownHandler = this._handleKeyDown.bind(this);
this._keyUpHandler = this._handleKeyUp.bind(this);
this._keyPressHandler = this._handleKeyPress.bind(this);
this._visibilityChangeHandler = this._handleVisibilityChange.bind(this);
this._windowBlurHandler = this._handleWindowBlur.bind(this);
if (element) {
this.attach(element);
}
this.preventDefault = options.preventDefault || false;
this.stopPropagation = options.stopPropagation || false;
}
attach(element) {
if (this._element) {
this.detach();
}
this._element = element;
this._element.addEventListener('keydown', this._keyDownHandler, false);
this._element.addEventListener('keypress', this._keyPressHandler, false);
this._element.addEventListener('keyup', this._keyUpHandler, false);
document.addEventListener('visibilitychange', this._visibilityChangeHandler, false);
window.addEventListener('blur', this._windowBlurHandler, false);
}
detach() {
if (!this._element) {
return;
}
this._element.removeEventListener('keydown', this._keyDownHandler);
this._element.removeEventListener('keypress', this._keyPressHandler);
this._element.removeEventListener('keyup', this._keyUpHandler);
this._element = null;
document.removeEventListener('visibilitychange', this._visibilityChangeHandler, false);
window.removeEventListener('blur', this._windowBlurHandler, false);
}
toKeyIdentifier(keyCode) {
keyCode = toKeyCode(keyCode);
const id = _keyCodeToKeyIdentifier[keyCode.toString()];
if (id) {
return id;
}
let hex = keyCode.toString(16).toUpperCase();
const length = hex.length;
for(let count = 0; count < 4 - length; count++){
hex = `0${hex}`;
}
return `U+${hex}`;
}
_handleKeyDown(event) {
const code = event.keyCode || event.charCode;
if (code === undefined) return;
const id = this.toKeyIdentifier(code);
this._keymap[id] = true;
this.fire('keydown', makeKeyboardEvent(event));
if (this.preventDefault) {
event.preventDefault();
}
if (this.stopPropagation) {
event.stopPropagation();
}
}
_handleKeyUp(event) {
const code = event.keyCode || event.charCode;
if (code === undefined) return;
const id = this.toKeyIdentifier(code);
delete this._keymap[id];
this.fire('keyup', makeKeyboardEvent(event));
if (this.preventDefault) {
event.preventDefault();
}
if (this.stopPropagation) {
event.stopPropagation();
}
}
_handleKeyPress(event) {
this.fire('keypress', makeKeyboardEvent(event));
if (this.preventDefault) {
event.preventDefault();
}
if (this.stopPropagation) {
event.stopPropagation();
}
}
_handleVisibilityChange() {
if (document.visibilityState === 'hidden') {
this._handleWindowBlur();
}
}
_handleWindowBlur() {
this._keymap = {};
this._lastmap = {};
}
update() {
for(const prop in this._lastmap){
delete this._lastmap[prop];
}
for(const prop in this._keymap){
if (this._keymap.hasOwnProperty(prop)) {
this._lastmap[prop] = this._keymap[prop];
}
}
}
isPressed(key) {
const keyCode = toKeyCode(key);
const id = this.toKeyIdentifier(keyCode);
return !!this._keymap[id];
}
wasPressed(key) {
const keyCode = toKeyCode(key);
const id = this.toKeyIdentifier(keyCode);
return !!this._keymap[id] && !!!this._lastmap[id];
}
wasReleased(key) {
const keyCode = toKeyCode(key);
const id = this.toKeyIdentifier(keyCode);
return !!!this._keymap[id] && !!this._lastmap[id];
}
}
export { Keyboard };