src/components/Script.js
import Component from '../systems/EntitySystem/Component';
import System from '../systems/System';
import { propsEnumStringify } from '../utils';
const EventFlags = {
NONE: 0,
MOUSE_DOWN: 1 << 0,
MOUSE_UP: 1 << 1,
MOUSE_MOVE: 1 << 2,
KEY_DOWN: 1 << 3,
KEY_UP: 1 << 4,
GAMEPAD_CONNECTED: 1 << 5,
GAMEPAD_DISCONNECTED: 1 << 6,
GAMEPAD_PROCESS: 1 << 7,
CONTACT_BEGIN: 1 << 8,
CONTACT_END: 1 << 9,
TOUCH_DOWN: 1 << 10,
TOUCH_UP: 1 << 11,
TOUCH_MOVE: 1 << 12,
};
EventFlags.MOUSE = EventFlags.MOUSE_DOWN | EventFlags.MOUSE_UP | EventFlags.MOUSE_MOVE;
EventFlags.KEY = EventFlags.KEY_DOWN | EventFlags.KEY_UP;
EventFlags.GAMEPAD = EventFlags.GAMEPAD_CONNECTED | EventFlags.GAMEPAD_DISCONNECTED | EventFlags.GAMEPAD_PROCESS;
EventFlags.INPUT = EventFlags.MOUSE | EventFlags.KEY | EventFlags.GAMEPAD;
EventFlags.CONTACT = EventFlags.CONTACT_BEGIN | EventFlags.CONTACT_END;
EventFlags.TOUCH = EventFlags.TOUCH_DOWN | EventFlags.TOUCH_UP | EventFlags.TOUCH_MOVE;
EventFlags.ALL = EventFlags.INPUT | EventFlags.CONTACT | EventFlags.TOUCH;
export default class Script extends Component {
static factory() {
return new Script();
}
static get propsTypes() {
return {
listenTo: `flags(${propsEnumStringify(EventFlags)})`
};
}
static get EventFlags() {
return EventFlags;
}
get listenTo() {
return this._listenTo;
}
set listenTo(value) {
if (typeof value !== 'number') {
throw new Error('`value` is not type of Number!');
}
const input = System.get('InputSystem');
if (!input) {
throw new Error('There is no registered InputSystem!');
}
const last = this._listenTo;
const listenTo = this._listenTo = value | 0;
const change = last ^ listenTo;
if (change & EventFlags.MOUSE_DOWN) {
if (listenTo & EventFlags.MOUSE_DOWN) {
input.events.on('mouse-down', this._onMouseDown);
} else {
input.events.off('mouse-down', this._onMouseDown);
}
}
if (change & EventFlags.MOUSE_UP) {
if (listenTo & EventFlags.MOUSE_UP) {
input.events.on('mouse-up', this._onMouseUp);
} else {
input.events.off('mouse-up', this._onMouseUp);
}
}
if (change & EventFlags.MOUSE_MOVE) {
if (listenTo & EventFlags.MOUSE_MOVE) {
input.events.on('mouse-move', this._onMouseMove);
} else {
input.events.off('mouse-move', this._onMouseMove);
}
}
if (change & EventFlags.KEY_DOWN) {
if (listenTo & EventFlags.KEY_DOWN) {
input.events.on('key-down', this._onKeyDown);
} else {
input.events.off('key-down', this._onKeyDown);
}
}
if (change & EventFlags.KEY_UP) {
if (listenTo & EventFlags.KEY_UP) {
input.events.on('key-up', this._onKeyUp);
} else {
input.events.off('key-up', this._onKeyUp);
}
}
if (change & EventFlags.GAMEPAD_CONNECTED) {
if (listenTo & EventFlags.GAMEPAD_CONNECTED) {
input.events.on('gamepad-connected', this._onGamepadConnected);
} else {
input.events.off('gamepad-connected', this._onGamepadConnected);
}
}
if (change & EventFlags.GAMEPAD_DISCONNECTED) {
if (listenTo & EventFlags.GAMEPAD_DISCONNECTED) {
input.events.on('gamepad-disconnected', this._onGamepadDisconnected);
} else {
input.events.off('gamepad-disconnected', this._onGamepadDisconnected);
}
}
if (change & EventFlags.GAMEPAD_PROCESS) {
if (listenTo & EventFlags.GAMEPAD_PROCESS) {
input.events.on('gamepad-process', this._onGamepadProcess);
} else {
input.events.off('gamepad-process', this._onGamepadProcess);
}
}
if (change & EventFlags.CONTACT_BEGIN) {
if (listenTo & EventFlags.CONTACT_BEGIN) {
input.events.on('contact-begin', this._onContactBegin);
} else {
input.events.off('contact-begin', this._onContactBegin);
}
}
if (change & EventFlags.CONTACT_END) {
if (listenTo & EventFlags.CONTACT_END) {
input.events.on('contact-end', this._onContactEnd);
} else {
input.events.off('contact-end', this._onContactEnd);
}
}
if (change & EventFlags.TOUCH_DOWN) {
if (listenTo & EventFlags.TOUCH_DOWN) {
input.events.on('touch-down', this._onTouchDown);
} else {
input.events.off('touch-down', this._onTouchDown);
}
}
if (change & EventFlags.TOUCH_UP) {
if (listenTo & EventFlags.TOUCH_UP) {
input.events.on('touch-up', this._onTouchUp);
} else {
input.events.off('touch-up', this._onTouchUp);
}
}
if (change & EventFlags.TOUCH_MOVE) {
if (listenTo & EventFlags.TOUCH_MOVE) {
input.events.on('touch-move', this._onTouchMove);
} else {
input.events.off('touch-move', this._onTouchMove);
}
}
}
constructor() {
super();
this._listenTo = EventFlags.NONE;
this._onMouseDown = this.onMouseDown.bind(this);
this._onMouseUp = this.onMouseUp.bind(this);
this._onMouseMove = this.onMouseMove.bind(this);
this._onKeyDown = this.onKeyDown.bind(this);
this._onKeyUp = this.onKeyUp.bind(this);
this._onGamepadConnected = this.onGamepadConnected.bind(this);
this._onGamepadDisconnected = this.onGamepadDisconnected.bind(this);
this._onGamepadProcess = this.onGamepadProcess.bind(this);
this._onContactBegin = this.onContactBegin.bind(this);
this._onContactEnd = this.onContactEnd.bind(this);
this._onTouchDown = this.onTouchDown.bind(this);
this._onTouchUp = this.onTouchUp.bind(this);
this._onTouchMove = this.onTouchMove.bind(this);
}
dispose() {
this.listenTo = EventFlags.NONE;
super.dispose();
}
onAttach() {
if ((this._listenTo | 0) & EventFlags.GAMEPAD_CONNECTED === 0) {
return;
}
const input = System.get('InputSystem');
if (!input) {
throw new Error('There is no registered InputSystem!');
}
for (const gamepad of input.gamepads.values()) {
this.onGamepadConnected(gamepad);
}
}
onDetach() {
if ((this._listenTo | 0) & EventFlags.GAMEPAD_DISCONNECTED === 0) {
return;
}
const input = System.get('InputSystem');
if (!input) {
throw new Error('There is no registered InputSystem!');
}
for (const gamepad of input.gamepads.values()) {
this.onGamepadDisconnected(gamepad);
}
}
onAction(name, ...args) {
if (name === 'update') {
return this.onUpdate(...args);
} else if (name === 'render') {
return this.onRender(...args);
} else if (name === 'render-layer') {
return this.onRenderLayer(...args);
} else if (name === 'preview') {
return this.onPreview(...args);
} else if (name === 'begin-contact') {
if (this._listenTo & EventFlags.CONTACT_BEGIN) {
return this.onContactBegin(...args);
}
} else if (name === 'end-contact') {
if (this._listenTo & EventFlags.CONTACT_END) {
return this.onContactEnd(...args);
}
}
}
onPropertySetup(name, value) {
if (name === 'listenTo') {
if (!(value instanceof Array)) {
throw new Error('`value` is not type of Array!');
}
let flags = EventFlags.NONE;
for (let i = 0, c = value.length; i < c; ++i) {
const flag = value[i];
if (flag === 'mouse-down') {
flags |= EventFlags.MOUSE_DOWN;
} else if (flag === 'mouse-up') {
flags |= EventFlags.MOUSE_UP;
} else if (flag === 'mouse-move') {
flags |= EventFlags.MOUSE_MOVE;
} else if (flag === 'mouse') {
flags |= EventFlags.MOUSE;
} else if (flag === 'key-down') {
flags |= EventFlags.KEY_DOWN;
} else if (flag === 'key-up') {
flags |= EventFlags.KEY_UP;
} else if (flag === 'key') {
flags |= EventFlags.KEY;
} else if (flag === 'gamepad-connected') {
flags |= EventFlags.GAMEPAD_CONNECTED;
} else if (flag === 'gamepad-disconnected') {
flags |= EventFlags.GAMEPAD_DISCONNECTED;
} else if (flag === 'gamepad-process') {
flags |= EventFlags.GAMEPAD_PROCESS;
} else if (flag === 'gamepad') {
flags |= EventFlags.GAMEPAD;
} else if (flag === 'input') {
flags |= EventFlags.INPUT;
} else if (flag === 'contact-begin') {
flags |= EventFlags.CONTACT_BEGIN;
} else if (flag === 'contact-end') {
flags |= EventFlags.CONTACT_END;
} else if (flag === 'contact') {
flags |= EventFlags.CONTACT;
} else if (flag === 'touch-down') {
flags |= EventFlags.TOUCH_DOWN;
} else if (flag === 'touch-up') {
flags |= EventFlags.TOUCH_UP;
} else if (flag === 'touch-move') {
flags |= EventFlags.TOUCH_MOVE;
} else if (flag === 'touch') {
flags |= EventFlags.TOUCH;
} else if (flag === 'all') {
flags |= EventFlags.ALL;
}
}
this.listenTo = flags;
} else {
super.onPropertySetup(name, value);
}
}
onPropertySerialize(name, value) {
if (name === 'listenTo') {
if ((value & EventFlags.ALL) === EventFlags.ALL) {
return [ 'all' ];
}
const result = [];
if ((value & EventFlags.MOUSE_DOWN) !== 0) {
result.push('mouse-down');
}
if ((value & EventFlags.MOUSE_UP) !== 0) {
result.push('mouse-up');
}
if ((value & EventFlags.MOUSE_MOVE) !== 0) {
result.push('mouse-move');
}
if ((value & EventFlags.KEY_DOWN) !== 0) {
result.push('key-down');
}
if ((value & EventFlags.KEY_UP) !== 0) {
result.push('key-up');
}
if ((value & EventFlags.GAMEPAD_CONNECTED) !== 0) {
result.push('gamepad-connected');
}
if ((value & EventFlags.GAMEPAD_DISCONNECTED) !== 0) {
result.push('gamepad-disconnected');
}
if ((value & EventFlags.GAMEPAD_PROCESS) !== 0) {
result.push('gamepad-process');
}
if ((value & EventFlags.CONTACT_BEGIN) !== 0) {
result.push('contact-begin');
}
if ((value & EventFlags.CONTACT_END) !== 0) {
result.push('contact-end');
}
if ((value & EventFlags.TOUCH_DOWN) !== 0) {
result.push('touch-down');
}
if ((value & EventFlags.TOUCH_UP) !== 0) {
result.push('touch-up');
}
if ((value & EventFlags.TOUCH_MOVE) !== 0) {
result.push('touch-move');
}
return result;
} else {
return super.onPropertySerialize(name, value);
}
}
onUpdate(deltaTime) {}
onRender(gl, renderer, deltaTime, layer) {}
onRenderLayer(gl, renderer, deltaTime, layer) {
this.onRender(gl, renderer, deltaTime, layer);
}
onPreview(gl, renderer, deltaTime) {
this.onRender(gl, renderer, deltaTime, null);
}
onMouseDown(unitVec, screenVec, button) {}
onMouseUp(unitVec, screenVec, button) {}
onMouseMove(unitVec, screenVec) {}
onKeyDown(code) {}
onKeyUp(code) {}
onGamepadConnected(gamepad) {}
onGamepadDisconnected(gamepad) {}
onGamepadProcess(gamepad) {}
onContactBegin(body, contact) {}
onContactEnd(body, contact) {}
onTouchDown(unitVec, screenVec, identifier) {}
onTouchUp(unitVec, screenVec, identifier) {}
onTouchMove(unitVec, screenVec, identifier) {}
}