UNPKG

playcanvas

Version:

Open-source WebGL/WebGPU 3D engine for the web

180 lines (179 loc) 5.32 kB
var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); import { DOUBLE_TAP_THRESHOLD, DOUBLE_TAP_VARIANCE } from "../constants.js"; import { InputSource } from "../input.js"; import { movementState } from "../utils.js"; import { VirtualJoystick } from "./virtual-joystick.js"; class SingleGestureSource extends InputSource { constructor() { super({ input: [0, 0], doubleTap: [0] }); /** * @type {ReturnType<typeof movementState>} * @private */ __publicField(this, "_movementState", movementState()); /** * @type {'joystick' | 'touch'} * @private */ __publicField(this, "_layout", "joystick"); /** * @type {Map<number, { x: number, y: number }>} * @private */ __publicField(this, "_pointerData", /* @__PURE__ */ new Map()); /** * @type {{ x: number, y: number, time: number }} * @private */ __publicField(this, "_lastPointer", { x: 0, y: 0, time: 0 }); /** * @type {VirtualJoystick} * @private */ __publicField(this, "_joystick"); this._joystick = new VirtualJoystick(); this._onPointerDown = this._onPointerDown.bind(this); this._onPointerMove = this._onPointerMove.bind(this); this._onPointerUp = this._onPointerUp.bind(this); } /** * Sets the layout of the single touch input source. Can be one of the following: * * - `joystick`: A virtual joystick. * - `touch`: A touch. * * Defaults to `joystick`. * * @type {'joystick' | 'touch'} */ set layout(value) { if (this._layout === value) { return; } this._layout = value; this.read(); this._pointerData.clear(); } /** * Gets the layout of the single touch input source. * * @type {'joystick' | 'touch'} */ get layout() { return this._layout; } get joystick() { return this._joystick; } /** * @private * @param {PointerEvent} event - The pointer event. */ _onPointerDown(event) { const { pointerType, pointerId, clientX, clientY } = event; this._movementState.down(event); if (pointerType !== "touch") { return; } this._element?.setPointerCapture(pointerId); this._pointerData.set(pointerId, { x: clientX, y: clientY }); const now = Date.now(); const sqrDist = (this._lastPointer.x - clientX) ** 2 + (this._lastPointer.y - clientY) ** 2; if (sqrDist < DOUBLE_TAP_VARIANCE && now - this._lastPointer.time < DOUBLE_TAP_THRESHOLD) { this.deltas.doubleTap.append([1]); } this._lastPointer.x = clientX; this._lastPointer.y = clientY; this._lastPointer.time = now; if (this._layout === "joystick") { this.fire("joystick:position", this._joystick.down(clientX, clientY)); } } /** * @param {PointerEvent} event - The pointer event. * @private */ _onPointerMove(event) { const { pointerType, pointerId, target, clientX, clientY } = event; const [movementX, movementY] = this._movementState.move(event); if (pointerType !== "touch") { return; } if (target !== this._element) { return; } const data = this._pointerData.get(pointerId); if (!data) { return; } data.x = clientX; data.y = clientY; if (this._layout === "joystick") { this.fire("joystick:position", this._joystick.move(clientX, clientY)); } else { this.deltas.input.append([movementX, movementY]); } } /** * @param {PointerEvent} event - The pointer event. * @private */ _onPointerUp(event) { const { pointerType, pointerId } = event; this._movementState.up(event); if (pointerType !== "touch") { return; } this._element?.releasePointerCapture(pointerId); const data = this._pointerData.get(pointerId); if (!data) { return; } this._pointerData.delete(pointerId); if (this._layout === "joystick") { this.fire("joystick:position", this._joystick.up()); } } /** * @param {HTMLElement} element - The element. */ attach(element) { super.attach(element); this._element = element; this._element.addEventListener("pointerdown", this._onPointerDown); this._element.addEventListener("pointermove", this._onPointerMove); this._element.addEventListener("pointerup", this._onPointerUp); this._element.addEventListener("pointercancel", this._onPointerUp); } detach() { if (!this._element) { return; } this._element.removeEventListener("pointerdown", this._onPointerDown); this._element.removeEventListener("pointermove", this._onPointerMove); this._element.removeEventListener("pointerup", this._onPointerUp); this._element.removeEventListener("pointercancel", this._onPointerUp); this._pointerData.clear(); super.detach(); } /** @override */ read() { this.deltas.input.append([this._joystick.value.x, this._joystick.value.y]); return super.read(); } destroy() { this._joystick.up(); super.destroy(); } } export { SingleGestureSource };