UNPKG

@tolokoban/tgd

Version:

ToloGameDev library for WebGL2

233 lines 18.4 kB
import { TgdEventPriority } from "./../event/index.js"; import { TgdUtilCyclicBuffer } from "./../utils/index.js"; const MOUSE_BUTTON_RIGHT = 2; export class TgdInputPointer { constructor(canvas) { this.canvas = canvas; this.eventTap = new TgdEventPriority(); this.eventTapMultiple = new TgdEventPriority(); this.eventMoveStart = new TgdEventPriority(); this.eventMove = new TgdEventPriority(); this.eventHover = new TgdEventPriority(); this.eventMoveEnd = new TgdEventPriority(); this.eventZoom = new TgdEventPriority(); /** * This is a tap only of the pointer touched for less that * `tapDelay` milliseconds. */ this.tapDelay = 300; this.moves = new TgdUtilCyclicBuffer(8); this.controlKeys = { altKey: false, ctrlKey: false, metaKey: false, shiftKey: false, }; this.start = { x: 0, y: 0, t: 0, fingersCount: 1, }; this.current = { x: 0, y: 0, t: 0, fingersCount: 1, }; this.previous = { x: 0, y: 0, t: 0, fingersCount: 1, }; /** * To manage multi taps. */ this.lastTap = null; this.tapsCount = 0; /** * If not null, the pointer is touching. */ this.pointerEvent = null; this.handleContextMenu = (event) => { event.preventDefault(); }; this.handleCanvasWheel = (event) => { const eventDelta = event.deltaX + event.deltaY + event.deltaZ; const delta = eventDelta > 0 ? 1 : -1; this.eventZoom.dispatch({ ...resolvePointerButtons(event), current: this.getPoint(event), direction: delta, preventDefault: () => event.preventDefault(), ...this.controlKeys, }); }; this.handlePointerDown = (event) => { if (!event.isPrimary) return; this.canvas?.setPointerCapture(event.pointerId); event.preventDefault(); event.stopPropagation(); this.pointerEvent = event; const point = this.getPoint(event); this.start = this.current = this.previous = point; this.eventMoveStart.dispatch({ ...resolvePointerButtons(event), start: point, current: point, previous: point, ...this.controlKeys, }); }; this.handlePointerMove = (event) => { const point = this.getPoint(event); this.moves.push(point); if (!event.isPrimary || !this.canvas) return; this.previous = this.current; this.current = point; const output = { ...resolvePointerButtons(event), start: this.start, current: this.current, previous: this.previous, ...this.controlKeys, }; this.eventHover.dispatch(output); if (this.pointerEvent) { this.eventMove.dispatch(output); } }; this.handlePointerUp = (event) => { if (!event.isPrimary || !this.pointerEvent) return; event.preventDefault(); this.current = this.getPoint(event); this.eventMoveEnd.dispatch({ ...resolvePointerButtons(event), start: this.start, current: this.current, previous: this.previous, ...this.controlKeys, }); this.pointerEvent = null; // Tap event. const seconds = event.timeStamp * 1e-3; if (seconds - this.start.t < this.tapDelay) { let tapEventEnabled = true; if (this.isMultiTap(this.start)) { this.tapsCount++; this.eventTapMultiple.dispatch({ ...resolvePointerButtons(event), tapsCount: this.tapsCount, ...this.current, start: this.start, ...this.controlKeys, preventTap: () => { tapEventEnabled = false; }, }); } else { this.tapsCount = 1; } if (tapEventEnabled) { this.eventTap.dispatch({ ...resolvePointerButtons(event), ...this.current, start: this.start, ...this.controlKeys, }); } this.lastTap = structuredClone(this.start); } }; if (!canvas) return; canvas.addEventListener("pointerdown", this.handlePointerDown, true); canvas.addEventListener("wheel", this.handleCanvasWheel); canvas.addEventListener("contextmenu", this.handleContextMenu); canvas.addEventListener("pointermove", this.handlePointerMove); canvas.addEventListener("pointerup", this.handlePointerUp); } get x() { return this.moves.newest?.x ?? 0; } get y() { return this.moves.newest?.y ?? 0; } get speedX() { const x1 = this.moves.newest?.x ?? 0; const t1 = Date.now() * 1e-3; const x0 = this.moves.oldest?.x ?? 0; const t0 = this.moves.oldest?.t ?? 0; return t0 < t1 ? (1e3 * (x1 - x0)) / (t1 - t0) : 0; } get speedY() { const y1 = this.moves.newest?.y ?? 0; const t1 = Date.now() * 1e-3; const y0 = this.moves.oldest?.y ?? 0; const t0 = this.moves.oldest?.t ?? 0; return t0 < t1 ? (1e3 * (y1 - y0)) / (t1 - t0) : 0; } isTouching(hitTest) { if (!this.pointerEvent) return false; if (!hitTest) return true; return hitTest(this.current); } detach() { const { canvas } = this; if (!canvas) return; canvas.removeEventListener("pointerdown", this.handlePointerDown); canvas.removeEventListener("wheel", this.handleCanvasWheel); canvas.removeEventListener("contextmenu", this.handleContextMenu); canvas.removeEventListener("pointermove", this.handlePointerMove); canvas.removeEventListener("pointerup", this.handlePointerUp); } isMultiTap(tap) { const { lastTap } = this; if (!lastTap) return false; if (tap.t - lastTap.t > this.tapDelay) return false; if (tap.fingersCount !== lastTap.fingersCount) return false; return true; } getPoint(event) { this.controlKeys = { altKey: event.altKey || event.buttons === MOUSE_BUTTON_RIGHT, ctrlKey: event.ctrlKey, metaKey: event.metaKey, shiftKey: event.shiftKey, }; const { left, top, width, height } = this.canvas ? this.canvas.getBoundingClientRect() : { left: 0, top: 0, width: 1, height: 1, }; const x = 2 * ((event.clientX - left) / width - 0.5); const y = -2 * ((event.clientY - top) / height - 0.5); return { x, y, t: event.timeStamp * 1e-3, fingersCount: 1 }; } } export function resolvePointerButtons({ buttons }) { const b = (v) => Boolean(buttons & v); return { buttons, buttonLeft: b(1), buttonRight: b(2), buttonMiddle: b(4), buttonBack: b(8), buttonForward: b(16), }; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9pbnRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9pbnB1dC9wb2ludGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLFlBQVksQ0FBQTtBQVE3QyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxZQUFZLENBQUE7QUFFaEQsTUFBTSxrQkFBa0IsR0FBRyxDQUFDLENBQUE7QUFFNUIsTUFBTSxPQUFPLGVBQWU7SUFrRHhCLFlBQTZCLE1BQTBCO1FBQTFCLFdBQU0sR0FBTixNQUFNLENBQW9CO1FBakQ5QyxhQUFRLEdBQUcsSUFBSSxnQkFBZ0IsRUFBcUMsQ0FBQTtRQUNwRSxxQkFBZ0IsR0FBRyxJQUFJLGdCQUFnQixFQUE2QyxDQUFBO1FBQ3BGLG1CQUFjLEdBQUcsSUFBSSxnQkFBZ0IsRUFBc0MsQ0FBQTtRQUMzRSxjQUFTLEdBQUcsSUFBSSxnQkFBZ0IsRUFBc0MsQ0FBQTtRQUN0RSxlQUFVLEdBQUcsSUFBSSxnQkFBZ0IsRUFBc0MsQ0FBQTtRQUN2RSxpQkFBWSxHQUFHLElBQUksZ0JBQWdCLEVBQXNDLENBQUE7UUFDekUsY0FBUyxHQUFHLElBQUksZ0JBQWdCLEVBQXNDLENBQUE7UUFDL0U7OztXQUdHO1FBQ0ksYUFBUSxHQUFHLEdBQUcsQ0FBQTtRQUViLFVBQUssR0FBRyxJQUFJLG1CQUFtQixDQUE2QixDQUFDLENBQUMsQ0FBQTtRQUU5RCxnQkFBVyxHQUFHO1lBQ2xCLE1BQU0sRUFBRSxLQUFLO1lBQ2IsT0FBTyxFQUFFLEtBQUs7WUFDZCxPQUFPLEVBQUUsS0FBSztZQUNkLFFBQVEsRUFBRSxLQUFLO1NBQ2xCLENBQUE7UUFDTyxVQUFLLEdBQStCO1lBQ3hDLENBQUMsRUFBRSxDQUFDO1lBQ0osQ0FBQyxFQUFFLENBQUM7WUFDSixDQUFDLEVBQUUsQ0FBQztZQUNKLFlBQVksRUFBRSxDQUFDO1NBQ2xCLENBQUE7UUFDTyxZQUFPLEdBQStCO1lBQzFD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