719 lines
19 KiB
JavaScript
719 lines
19 KiB
JavaScript
import {
|
|
MemoryHelper,
|
|
} from "./memoryhelper.js";
|
|
|
|
import { CharNumber } from "./charnumber.js";
|
|
import { Keymap } from "./keymap.js";
|
|
import { MouseButton } from "./mousebutton.js";
|
|
import { GamepadButton } from "./gamepadbutton.js";
|
|
import { TouchPhase } from "./touchphase.js";
|
|
import { TouchFlags } from "./touchflags.js";
|
|
|
|
export class FourCC {
|
|
/**
|
|
* {Number} _code;
|
|
*/
|
|
|
|
/**
|
|
*
|
|
* @param {String} a
|
|
* @param {String} b
|
|
* @param {String} c
|
|
* @param {String} d
|
|
*/
|
|
constructor(a, b, c, d) {
|
|
this._code = (a.charCodeAt() << 24)
|
|
| (b.charCodeAt() << 16)
|
|
| (c.charCodeAt() << 8)
|
|
| d.charCodeAt();
|
|
}
|
|
|
|
/**
|
|
* @returns {Number}
|
|
*/
|
|
toInt32() {
|
|
return this._code;
|
|
}
|
|
}
|
|
|
|
|
|
export class InputDevice {
|
|
|
|
/**
|
|
*
|
|
* name;
|
|
* layout;
|
|
* deviceId;
|
|
* usages;
|
|
* description;
|
|
*
|
|
* _inputState;
|
|
*/
|
|
|
|
/**
|
|
*
|
|
* @param {Number} name
|
|
* @param {String} layout
|
|
* @param {Number} deviceId
|
|
* @param {String[]} usages
|
|
* @param {Object} description
|
|
*/
|
|
constructor(name, layout, deviceId, usages, description) {
|
|
this.name = name;
|
|
this.layout = layout;
|
|
this.deviceId = deviceId;
|
|
this.usages = usages;
|
|
this.description = description;
|
|
|
|
this._inputState = null;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param {IInputState} state
|
|
*/
|
|
updateState(state) {
|
|
this._inputState = state;
|
|
}
|
|
|
|
queueEvent(event) {
|
|
throw new Error(`Please implement this method. event:${event}`);
|
|
}
|
|
|
|
/**
|
|
* @returns {IInputState}
|
|
*/
|
|
get currentState() {
|
|
return this._inputState;
|
|
}
|
|
}
|
|
|
|
export class Mouse extends InputDevice {
|
|
/**
|
|
* @param {(MouseEvent|WheelEvent)} event
|
|
*/
|
|
queueEvent(event) {
|
|
this.updateState(new MouseState(event));
|
|
}
|
|
}
|
|
|
|
export class Keyboard extends InputDevice {
|
|
static get keycount() { return 110; }
|
|
/**
|
|
*
|
|
* @param {KeyboardEvent} event
|
|
*/
|
|
queueEvent(event) {
|
|
this.updateState(new KeyboardState(event, this.currentState));
|
|
}
|
|
}
|
|
|
|
export class Touchscreen extends InputDevice {
|
|
/**
|
|
* @param {TouchScreenEvent} event
|
|
*/
|
|
queueEvent(event, time) {
|
|
this.updateState(new TouchscreenState(event, this.currentState, time));
|
|
}
|
|
}
|
|
|
|
export class Gamepad extends InputDevice {
|
|
/**
|
|
* @param {GamepadButtonEvent | GamepadAxisEvent} event
|
|
*/
|
|
queueEvent(event) {
|
|
this.updateState(new GamepadState(event));
|
|
}
|
|
}
|
|
|
|
export class InputEvent {
|
|
static get invalidEventId() { return 0; }
|
|
static get size() { return 20; }
|
|
|
|
/**
|
|
* field offset 0
|
|
* @member {Number} type;
|
|
*
|
|
* field offset 4
|
|
* @member {Number} sizeInBytes;
|
|
*
|
|
* field offset 6
|
|
* @member {Number} deviceId;
|
|
*
|
|
* field offset 8
|
|
* @member {Number} time;
|
|
*
|
|
* field offset 16
|
|
* @member {Number} eventId;
|
|
*/
|
|
|
|
/**
|
|
*
|
|
* @param {Number} type
|
|
* @param {Number} sizeInBytes
|
|
* @param {Number} deviceId
|
|
* @param {Number} time
|
|
*/
|
|
constructor(type, sizeInBytes, deviceId, time) {
|
|
this.type = type;
|
|
this.sizeInBytes = sizeInBytes;
|
|
this.deviceId = deviceId;
|
|
this.time = time;
|
|
this.eventId = InputEvent.invalidEventId;
|
|
}
|
|
|
|
/**
|
|
* @returns {ArrayBuffer}
|
|
*/
|
|
get buffer() {
|
|
let _buffer = new ArrayBuffer(InputEvent.size);
|
|
let view = new DataView(_buffer);
|
|
view.setInt32(0, this.type, true);
|
|
view.setInt16(4, this.sizeInBytes, true);
|
|
view.setInt16(6, this.deviceId, true);
|
|
view.setFloat64(8, this.time, true);
|
|
view.setInt16(16, this.sizeInBytes, true);
|
|
return _buffer;
|
|
}
|
|
}
|
|
|
|
export class IInputState {
|
|
/**
|
|
* @returns {ArrayBuffer}
|
|
*/
|
|
get buffer() {
|
|
throw new Error('Please implement this field');
|
|
}
|
|
/**
|
|
* @returns {Number}
|
|
*/
|
|
get format() {
|
|
throw new Error('Please implement this field');
|
|
}
|
|
}
|
|
|
|
export class MouseState extends IInputState {
|
|
static get size() { return 30; }
|
|
static get format() { return new FourCC('M', 'O', 'U', 'S').toInt32(); }
|
|
|
|
/**
|
|
* field offset 0
|
|
* @member {Array} position;
|
|
*
|
|
* field offset 8
|
|
* @member {Array} delta;
|
|
*
|
|
* field offset 16
|
|
* @member {Array} scroll;
|
|
*
|
|
* field offset 24
|
|
* @member {ArrayBuffer} buttons;
|
|
*
|
|
* field offset 26
|
|
* @member {Array} displayIndex;
|
|
*
|
|
* field offset 28
|
|
* @member {Array} clickCount;
|
|
*/
|
|
|
|
/**
|
|
* @param {MouseEvent | WheelEvent} event
|
|
*/
|
|
constructor(event) {
|
|
super();
|
|
|
|
this.position = [event.clientX, event.clientY];
|
|
this.delta = [event.movementX, -event.movementY];
|
|
this.scroll = [0, 0];
|
|
if(event.type === 'wheel') {
|
|
this.scroll = [event.deltaX, event.deltaY];
|
|
}
|
|
this.buttons = new ArrayBuffer(2);
|
|
|
|
const left = event.buttons & 1 << 0;
|
|
const right = event.buttons & 1 << 1;
|
|
const middle = event.buttons & 1 << 2;
|
|
const back = event.buttons & 1 << 3;
|
|
const forward = event.buttons & 1 << 4;
|
|
|
|
MemoryHelper.writeSingleBit(this.buttons, MouseButton.Left, left);
|
|
MemoryHelper.writeSingleBit(this.buttons, MouseButton.Right, right);
|
|
MemoryHelper.writeSingleBit(this.buttons, MouseButton.Middle, middle);
|
|
MemoryHelper.writeSingleBit(this.buttons, MouseButton.Forward, forward);
|
|
MemoryHelper.writeSingleBit(this.buttons, MouseButton.Back, back);
|
|
}
|
|
|
|
/**
|
|
* @returns {ArrayBuffer}
|
|
*/
|
|
get buffer() {
|
|
const size = MouseState.size;
|
|
const buttons = new Uint16Array(this.buttons)[0];
|
|
let _buffer = new ArrayBuffer(size);
|
|
let view = new DataView(_buffer);
|
|
view.setFloat32(0, this.position[0], true);
|
|
view.setFloat32(4, this.position[1], true);
|
|
view.setFloat32(8, this.delta[0], true);
|
|
view.setFloat32(12, this.delta[1], true);
|
|
view.setFloat32(16, this.scroll[0], true);
|
|
view.setFloat32(20, this.scroll[1], true);
|
|
view.setUint16(24, buttons, true);
|
|
view.setUint16(26, this.displayIndex, true);
|
|
view.setUint16(28, this.clickCount, true);
|
|
return _buffer;
|
|
}
|
|
|
|
/**
|
|
* @returns {Number}
|
|
*/
|
|
get format() {
|
|
return MouseState.format;
|
|
}
|
|
}
|
|
|
|
export class KeyboardState extends IInputState {
|
|
static get sizeInBits() { return Keyboard.keycount; }
|
|
static get sizeInBytes() { return (KeyboardState.sizeInBits + 7) >> 3; }
|
|
static get format() { return new FourCC('K', 'E', 'Y', 'S').toInt32(); }
|
|
|
|
/**
|
|
* field offset 0
|
|
* @number {ArrayBuffer} keys;
|
|
*/
|
|
|
|
/**
|
|
* @param {KeyboardEvent} event
|
|
*/
|
|
constructor(event, state) {
|
|
super();
|
|
if (state == null || state.keys == null) {
|
|
this.keys = new ArrayBuffer(KeyboardState.sizeInBytes);
|
|
} else {
|
|
this.keys = state.keys;
|
|
}
|
|
let value = false;
|
|
switch(event.type) {
|
|
case 'keydown':
|
|
value = true;
|
|
break;
|
|
case 'keyup':
|
|
value = false;
|
|
break;
|
|
default:
|
|
throw new Error(`unknown event type ${event.type})`);
|
|
}
|
|
const key = Keymap[event.code];
|
|
MemoryHelper.writeSingleBit(this.keys, key, value);
|
|
}
|
|
|
|
/**
|
|
* @returns {ArrayBuffer}
|
|
*/
|
|
get buffer() {
|
|
return this.keys;
|
|
}
|
|
|
|
/**
|
|
* @returns {Number}
|
|
*/
|
|
get format() {
|
|
return KeyboardState.format;
|
|
}
|
|
}
|
|
|
|
export class TouchState {
|
|
static get format() { return new FourCC('T', 'O', 'U', 'C').toInt32(); }
|
|
static get size() { return 56; }
|
|
static incrementTouchId() {
|
|
if(TouchState._currentTouchId === undefined) {
|
|
TouchState._currentTouchId = 0;
|
|
}
|
|
return ++TouchState._currentTouchId;
|
|
}
|
|
static prevTouches() {
|
|
if(TouchState._prevTouches === undefined) {
|
|
// max touch count is 10
|
|
TouchState._prevTouches = new Array(10);
|
|
}
|
|
return TouchState._prevTouches;
|
|
}
|
|
|
|
/**
|
|
* field offset 0
|
|
* @number {Number} touchId;
|
|
* field offset 4
|
|
* @number {Number[]} position;
|
|
* field offset 12
|
|
* @number {Number[]} delta;
|
|
* field offset 20
|
|
* @number {Number} pressure;
|
|
* field offset 24
|
|
* @number {Number[]} radius;
|
|
* field offset 32
|
|
* @number {Number} phase;
|
|
* field offset 33
|
|
* @number {Number} tapCount;
|
|
* field offset 34
|
|
* @number {Number} displayIndex;
|
|
* field offset 35
|
|
* @number {Number} flag;
|
|
* field offset 36
|
|
* @number {Number} padding;
|
|
* field offset 40
|
|
* @number {Number} startTime;
|
|
* field offset 48
|
|
* @number {Number[]} startPosition;
|
|
*/
|
|
|
|
|
|
/**
|
|
* @param {Touch} touchId
|
|
* @param {TouchState} prevState
|
|
* @param {Number[]} position
|
|
* @param {Number} pressure
|
|
* @param {Number[]} radius
|
|
* @param {TouchPhase} phaseId
|
|
* @param {Number} time
|
|
*/
|
|
constructor(touchId, prevState, position, pressure, radius, phaseId, time) {
|
|
this.touchId = touchId;
|
|
this.position = position != null ? position.slice() : null;
|
|
if(phaseId == TouchPhase.Moved) {
|
|
this.delta = [this.position[0] - prevState.position[0], this.position[1] - prevState.position[1]];
|
|
} else {
|
|
this.delta = [0, 0];
|
|
}
|
|
this.pressure = pressure;
|
|
this.radius = radius != null ? radius.slice(): null;
|
|
this.phaseId = phaseId;
|
|
this.tapCount = 0;
|
|
this.displayIndex = 0;
|
|
this.flags = 0;
|
|
this.padding = 0;
|
|
if(phaseId == TouchPhase.Began) {
|
|
this.startTime = time;
|
|
this.startPosition = this.position.slice();
|
|
} else {
|
|
this.startTime = prevState != null ? prevState.startTime : null;
|
|
this.startPosition = prevState != null ? prevState.startPosition.slice() : null;
|
|
}
|
|
}
|
|
|
|
|
|
copy() {
|
|
let state = new TouchState();
|
|
state.touchId = this.touchId;
|
|
state.position = this.position.slice();
|
|
state.delta = this.delta.slice();
|
|
state.pressure = this.pressure;
|
|
state.radius = this.radius.slice();
|
|
state.phaseId = this.phaseId;
|
|
state.tapCount = this.tapCount;
|
|
state.displayIndex = this.displayIndex;
|
|
state.flags = this.flags;
|
|
state.padding = this.padding;
|
|
state.startTime = this.startTime;
|
|
state.startPosition = this.startPosition.slice();
|
|
return state;
|
|
}
|
|
|
|
/**
|
|
* @returns {ArrayBuffer}
|
|
*/
|
|
get buffer() {
|
|
const size = TouchState.size; // todo
|
|
let _buffer = new ArrayBuffer(size);
|
|
let view = new DataView(_buffer);
|
|
|
|
view.setInt32(0, this.touchId, true);
|
|
view.setFloat32(4, this.position[0], true);
|
|
view.setFloat32(8, this.position[1], true);
|
|
view.setFloat32(12, this.delta[0], true);
|
|
view.setFloat32(16, this.delta[1], true);
|
|
view.setFloat32(20, this.pressure, true);
|
|
view.setFloat32(24, this.radius[0], true);
|
|
view.setFloat32(28, this.radius[1], true);
|
|
view.setInt8(32, this.phaseId, true);
|
|
view.setInt8(33, this.tapCount, true);
|
|
view.setInt8(34, this.displayIndex, true);
|
|
view.setInt8(35, this.flags, true);
|
|
view.setInt32(36, this.padding, true);
|
|
view.setFloat64(40, this.startTime, true);
|
|
view.setFloat32(48, this.startPosition[0], true);
|
|
view.setFloat32(52, this.startPosition[1], true);
|
|
return _buffer;
|
|
}
|
|
|
|
/**
|
|
* @returns {Number}
|
|
*/
|
|
get format() {
|
|
return TouchState.format;
|
|
}
|
|
}
|
|
|
|
export class TouchscreenState extends IInputState {
|
|
static get maxTouches() { return 10; }
|
|
static get format() { return new FourCC('T', 'S', 'C', 'R').toInt32(); }
|
|
static convertPhaseId(type) {
|
|
let phaseId = TouchPhase.Stationary;
|
|
switch(type) {
|
|
case 'touchstart':
|
|
phaseId = TouchPhase.Began; break;
|
|
case 'touchend':
|
|
phaseId = TouchPhase.Ended; break;
|
|
case 'touchmove':
|
|
phaseId = TouchPhase.Moved; break;
|
|
case 'touchcancel':
|
|
phaseId = TouchPhase.Canceled; break;
|
|
}
|
|
return phaseId;
|
|
}
|
|
|
|
/**
|
|
* @param {TouchEvent} event
|
|
* @param {TouchScreenState} state
|
|
* @param {Date} time
|
|
*/
|
|
constructor(event, state, time) {
|
|
super();
|
|
|
|
switch(event.type) {
|
|
// `click` event is called when releasing mouse button or finger on screen.
|
|
case 'click' : {
|
|
this.touchData = new Array(state.touchData.length);
|
|
for(let i = 0; i < state.touchData.length; i++) {
|
|
this.touchData[i] = state.touchData[i];
|
|
if(this.touchData[i].phaseId == TouchPhase.Ended) {
|
|
this.touchData[i].tapCount = 1;
|
|
this.touchData[i].flags |= TouchFlags.Tap;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default: {
|
|
let touches = event.changedTouches;
|
|
this.touchData = new Array(touches.length);
|
|
for(let i = 0; i < touches.length; i++) {
|
|
const touch = touches[i];
|
|
const position = [touch.clientX, touch.clientY];
|
|
const phaseId = TouchscreenState.convertPhaseId(event.type);
|
|
const pressure = touch.force;
|
|
const radius = [touch.radiusX, touch.radiusY];
|
|
|
|
// `touchId` in InputSystem must be set uniquely.
|
|
// The numbers of `touch.identifier` in Web API are reused, so these are not unique.
|
|
const touchId = phaseId == TouchPhase.Began ? TouchState.incrementTouchId() : TouchState.prevTouches()[touch.identifier].touchId;
|
|
const prevState = phaseId != TouchPhase.Began ? TouchState.prevTouches()[touch.identifier] : null;
|
|
const touchData = new TouchState(touchId, prevState, position, pressure, radius, phaseId, time);
|
|
|
|
// cache state
|
|
TouchState.prevTouches()[touch.identifier] = touchData;
|
|
this.touchData[i] = touchData;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @returns {ArrayBuffer}
|
|
*/
|
|
get buffer() {
|
|
const size = TouchState.size * this.touchData.length;
|
|
let _buffer = new ArrayBuffer(size);
|
|
let view = new Uint8Array(_buffer);
|
|
for(let i = 0; i < this.touchData.length; i++) {
|
|
view.set(new Uint8Array(this.touchData[i].buffer), TouchState.size * i);
|
|
}
|
|
return _buffer;
|
|
}
|
|
|
|
/**
|
|
* @returns {Number}
|
|
*/
|
|
get format() {
|
|
return TouchscreenState.format;
|
|
}
|
|
}
|
|
|
|
export class GamepadState extends IInputState {
|
|
static get size() { return 28; }
|
|
static get format() { return new FourCC('G', 'P', 'A', 'D').toInt32(); }
|
|
|
|
/**
|
|
* field offset 0
|
|
* @member buttons;
|
|
*
|
|
* field offset 4
|
|
* @member leftStick;
|
|
*
|
|
* field offset 12
|
|
* @member rightStick;
|
|
*
|
|
* field offset 20
|
|
* @member leftTrigger;
|
|
*
|
|
* field offset 24
|
|
* @member rightTrigger;
|
|
*/
|
|
|
|
/**
|
|
*
|
|
* @param {GamepadButtonEvent | GamepadAxisEvent} event
|
|
*/
|
|
constructor(event) {
|
|
super();
|
|
const gamepad = event.gamepad;
|
|
const buttons = event.gamepad.buttons;
|
|
|
|
this.buttons = new ArrayBuffer(4);
|
|
this.leftStick = [ gamepad.axes[0], -gamepad.axes[1] ];
|
|
this.rightStick = [ gamepad.axes[2], -gamepad.axes[3] ];
|
|
this.leftTrigger = buttons[6].value;
|
|
this.rightTrigger = buttons[7].value;
|
|
|
|
// see https://w3c.github.io/gamepad/#remapping
|
|
MemoryHelper.writeSingleBit(this.buttons, GamepadButton.A, buttons[0].pressed);
|
|
MemoryHelper.writeSingleBit(this.buttons, GamepadButton.B, buttons[1].pressed);
|
|
MemoryHelper.writeSingleBit(this.buttons, GamepadButton.X, buttons[2].pressed);
|
|
MemoryHelper.writeSingleBit(this.buttons, GamepadButton.Y, buttons[3].pressed);
|
|
MemoryHelper.writeSingleBit(this.buttons, GamepadButton.LeftShoulder, buttons[4].pressed);
|
|
MemoryHelper.writeSingleBit(this.buttons, GamepadButton.RightShoulder, buttons[5].pressed);
|
|
MemoryHelper.writeSingleBit(this.buttons, GamepadButton.LeftTrigger, buttons[6].pressed);
|
|
MemoryHelper.writeSingleBit(this.buttons, GamepadButton.RightTrigger, buttons[7].pressed);
|
|
MemoryHelper.writeSingleBit(this.buttons, GamepadButton.Select, buttons[8].pressed);
|
|
MemoryHelper.writeSingleBit(this.buttons, GamepadButton.Start, buttons[9].pressed);
|
|
MemoryHelper.writeSingleBit(this.buttons, GamepadButton.LeftStick, buttons[10].pressed);
|
|
MemoryHelper.writeSingleBit(this.buttons, GamepadButton.RightStick, buttons[11].pressed);
|
|
MemoryHelper.writeSingleBit(this.buttons, GamepadButton.DpadUp, buttons[12].pressed);
|
|
MemoryHelper.writeSingleBit(this.buttons, GamepadButton.DpadDown, buttons[13].pressed);
|
|
MemoryHelper.writeSingleBit(this.buttons, GamepadButton.DpadLeft, buttons[14].pressed);
|
|
MemoryHelper.writeSingleBit(this.buttons, GamepadButton.DpadRight, buttons[15].pressed);
|
|
}
|
|
|
|
/**
|
|
* @returns {ArrayBuffer}
|
|
*/
|
|
get buffer() {
|
|
const size = GamepadState.size;
|
|
let _buffer = new ArrayBuffer(size);
|
|
let view = new DataView(_buffer);
|
|
view.setUint32(0, new Uint32Array(this.buttons)[0], true);
|
|
view.setFloat32(4, this.leftStick[0], true);
|
|
view.setFloat32(8, this.leftStick[1], true);
|
|
view.setFloat32(12, this.rightStick[0], true);
|
|
view.setFloat32(16, this.rightStick[1], true);
|
|
view.setFloat32(20, this.leftTrigger, true);
|
|
view.setFloat32(24, this.rightTrigger, true);
|
|
return _buffer;
|
|
}
|
|
|
|
/**
|
|
* @returns {Number}
|
|
*/
|
|
get format() {
|
|
return GamepadState.format;
|
|
}
|
|
}
|
|
|
|
export class TextEvent {
|
|
static get format() { return new FourCC('T', 'E', 'X', 'T').toInt32(); }
|
|
|
|
/**
|
|
* field offset 0
|
|
* @member {InputEvent} baseEvent;
|
|
*
|
|
* field offset 20
|
|
* @member {Number} character;
|
|
*/
|
|
|
|
/**
|
|
*
|
|
* @param {Number} deviceId
|
|
* @param {KeyboardEvent} event
|
|
* @param {Number} time
|
|
* @returns {TextEvent}
|
|
|
|
*/
|
|
static create(deviceId, event, time) {
|
|
const eventSize = InputEvent.size + MemoryHelper.sizeOfInt;
|
|
|
|
let textEvent = new TextEvent();
|
|
textEvent.baseEvent = new InputEvent(TextEvent.format, eventSize, deviceId, time);
|
|
textEvent.character = CharNumber[event.key];
|
|
return textEvent;
|
|
}
|
|
|
|
/**
|
|
* @returns {ArrayBuffer}
|
|
*/
|
|
get buffer() {
|
|
const size = InputEvent.size + MemoryHelper.sizeOfInt;
|
|
let _buffer = new ArrayBuffer(size);
|
|
let arrayView = new Uint8Array(_buffer);
|
|
let dataView = new DataView(_buffer);
|
|
arrayView.set(new Uint8Array(this.baseEvent.buffer), 0);
|
|
dataView.setInt32(InputEvent.size, this.character, true);
|
|
return _buffer;
|
|
}
|
|
}
|
|
|
|
export class StateEvent {
|
|
static get format() { return new FourCC('S', 'T', 'A', 'T').toInt32(); }
|
|
|
|
/**
|
|
* field offset 0
|
|
* @member {InputEvent} baseEvent;
|
|
*
|
|
* field offset 20
|
|
* @member {Number} stateFormat;
|
|
*
|
|
* field offset 24
|
|
* @member {ArrayBuffer} stateData;
|
|
*/
|
|
|
|
/**
|
|
*
|
|
* @param {InputDevice} device
|
|
* @param {Number} time
|
|
* @returns {StateEvent}
|
|
*/
|
|
static from(device, time) {
|
|
return StateEvent.fromState(device.currentState, device.deviceId, time);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param {IInputState} state
|
|
* @param {Number} deviceId
|
|
* @param {Number} time
|
|
*/
|
|
static fromState(state, deviceId, time) {
|
|
const stateData = state.buffer;
|
|
const stateSize = stateData.byteLength;
|
|
const eventSize = InputEvent.size + MemoryHelper.sizeOfInt + stateSize;
|
|
|
|
let stateEvent = new StateEvent();
|
|
stateEvent.baseEvent = new InputEvent(StateEvent.format, eventSize, deviceId, time);
|
|
stateEvent.stateFormat = state.format;
|
|
stateEvent.stateData = stateData;
|
|
return stateEvent;
|
|
}
|
|
|
|
/**
|
|
* @returns {ArrayBuffer}
|
|
*/
|
|
get buffer() {
|
|
const stateSize = this.stateData.byteLength;
|
|
const size = InputEvent.size + MemoryHelper.sizeOfInt + stateSize;
|
|
let _buffer = new ArrayBuffer(size);
|
|
let uint8View = new Uint8Array(_buffer);
|
|
let dataView = new DataView(_buffer);
|
|
uint8View.set(new Uint8Array(this.baseEvent.buffer), 0);
|
|
dataView.setInt32(InputEvent.size, this.stateFormat, true);
|
|
uint8View.set(new Uint8Array(this.stateData), InputEvent.size+MemoryHelper.sizeOfInt);
|
|
return _buffer;
|
|
}
|
|
}
|