import { $EventManager, $EventMap } from "./$EventManager"; import { type $Node } from "./node/$Node"; export class $PointerManager extends $EventManager<$PointerManagerEventMap> { $node: $Node; map = new Map(); constructor($node: $Node) { super(); this.$node = $node; this.$node.on('pointerdown', (e) => this.down(e)) this.$node.on('pointerup', (e) => this.up(e)) this.$node.on('pointermove', (e) => this.move(e)) this.$node.on('pointercancel', (e) => this.cancel(e)) } protected down(e: PointerEvent) { const pointer = new $Pointer(this, this.toData(e), $(e.target!)) this.map.set(pointer.id, pointer); this.fire('down', pointer, e); } protected up(e: PointerEvent) { const pointer = this.map.get(e.pointerId); if (!pointer) return; this.map.delete(e.pointerId); this.fire('up', pointer, e); } protected move(e: PointerEvent) { const pointer = this.map.get(e.pointerId); if (!pointer) return; this.map.set(pointer.id, pointer); pointer.update(this.toData(e)); this.fire('move', pointer, e); } protected cancel(e: PointerEvent) { const pointer = this.map.get(e.pointerId); if (!pointer) return; pointer.update(this.toData(e)); this.map.delete(pointer.id); this.fire('cancel', pointer, e); } protected toData(e: PointerEvent): $PointerData { return { id: e.pointerId, type: e.pointerType as PointerType, width: e.width, height: e.height, x: e.x, y: e.y, movement_x: e.movementX, movement_y: e.movementY } } } export interface $PointerManagerEventMap extends $EventMap { up: [$Pointer, MouseEvent]; down: [$Pointer, MouseEvent]; move: [$Pointer, MouseEvent]; cancel: [$Pointer, MouseEvent]; } export interface $Pointer extends $PointerData {} export class $Pointer { initial_x: number; initial_y: number; $target: $Node; protected manager: $PointerManager; constructor(manager: $PointerManager, data: $PointerData, target: $Node) { Object.assign(this, data); this.manager = manager; this.$target = target; this.initial_x = data.x; this.initial_y = data.y; } get move_x() { return this.x - this.initial_x } get move_y() { return this.y - this.initial_y } update(data: $PointerData) { Object.assign(this, data); return this; } delete() { this.manager.map.delete(this.id); return this; } } export interface $PointerData { id: number; type: PointerType; width: number; height: number; x: number; y: number; movement_x: number; movement_y: number; } export type PointerType = 'mouse' | 'pen' | 'touch'