From 23575dd5165c25936b2bda50f1c3f00d796d893c Mon Sep 17 00:00:00 2001 From: hypercross Date: Fri, 17 Apr 2026 21:55:14 +0800 Subject: [PATCH] feat: dnd --- packages/framework/src/index.ts | 4 ++ packages/framework/src/utils/dnd.ts | 70 +++++++++++++++++++++++++++ packages/framework/src/utils/index.ts | 1 + 3 files changed, 75 insertions(+) create mode 100644 packages/framework/src/utils/dnd.ts diff --git a/packages/framework/src/index.ts b/packages/framework/src/index.ts index 04aadec..7b780f9 100644 --- a/packages/framework/src/index.ts +++ b/packages/framework/src/index.ts @@ -2,6 +2,10 @@ export { DisposableBag } from './utils'; export type { IDisposable, DisposableItem } from './utils'; +// Drag & drop utilities +export { dragDropEventEffect, DragDropEventType } from './utils'; +export type { DragDropEvent } from './utils'; + // Data-driven object spawning export { spawnEffect } from './spawner'; export type { Spawner } from './spawner'; diff --git a/packages/framework/src/utils/dnd.ts b/packages/framework/src/utils/dnd.ts new file mode 100644 index 0000000..ae880a4 --- /dev/null +++ b/packages/framework/src/utils/dnd.ts @@ -0,0 +1,70 @@ +type PointerRecord = { + id: number; + x: number; + y: number; +} + +export enum DragDropEventType { + DOWN, + UP, + MOVE, +} +export type DragDropEvent = { + type: DragDropEventType, + relativeX: number; + relativeY: number; +} + +export function dragDropEventEffect( + gameObject: Phaser.GameObjects.GameObject, +) { + let down: PointerRecord | null; + let up: PointerRecord | null; + + function onPointerDown(pointer: Phaser.Input.Pointer) { + down = { + id: pointer.id, + x: pointer.x, + y: pointer.y + } + up = null; + + const type = DragDropEventType.DOWN; + const relativeX = pointer.x - down.x; + const relativeY = pointer.y - down.y; + gameObject.emit('drag', {type, relativeX, relativeY}); + } + + function onPointerUp(pointer: Phaser.Input.Pointer) { + if(!down) return; + up = { + id: pointer.id, + x: pointer.x, + y: pointer.y + } + + const type = DragDropEventType.UP; + const relativeX = pointer.x - down.x; + const relativeY = pointer.y - down.y; + gameObject.emit('drag', {type, relativeX, relativeY}); + } + + function onPointerMove(pointer: Phaser.Input.Pointer) { + if(!down || up) return; + if(down.id !== pointer.id) return; + + const type = DragDropEventType.MOVE; + const relativeX = pointer.x - down.x; + const relativeY = pointer.y - down.y; + gameObject.emit('drag', {type, relativeX, relativeY}); + } + + gameObject.on('pointerdown', onPointerDown); + gameObject.on('pointerup', onPointerUp); + gameObject.scene.input.on('pointermove', onPointerMove); + return function () { + gameObject.off('pointerdown', onPointerDown); + gameObject.off('pointerup', onPointerUp); + gameObject.scene.input.off('pointermove', onPointerMove); + } +} \ No newline at end of file diff --git a/packages/framework/src/utils/index.ts b/packages/framework/src/utils/index.ts index 106634b..53ba7f5 100644 --- a/packages/framework/src/utils/index.ts +++ b/packages/framework/src/utils/index.ts @@ -1,2 +1,3 @@ export { DisposableBag } from './disposable'; export type { IDisposable, DisposableItem } from './disposable'; +export { dragDropEventEffect, DragDropEventType, type DragDropEvent } from './dnd';