@combos-fun/plugin-renderer-3d-event 0.0.42 → 0.0.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/agent-skill.md CHANGED
@@ -21,7 +21,15 @@ import {
21
21
 
22
22
  `componentName = 'Event3D'`, `systemName = 'Event3DSystem'`. Use `game.getSystem(Event3DSystem)`, not a string.
23
23
 
24
- Hit testing uses the GameObject's mesh (every 3D renderer tags `Object3D.userData.combosGameObjectId`). There is no separate `hitArea` shape.
24
+ Hit testing uses the GameObject's mesh (every 3D renderer tags `Object3D.userData.combosGameObjectId`). `InstancedMesh` hits use `intersection.instanceId` → `userData.combosInstanceGameObjectIds`.
25
+
26
+ Optional `hitArea` adds an invisible pick mesh (`box` / `sphere` / `plane`) under the `Transform3D` root — use it for empty parents or a simpler volume than a GLB:
27
+
28
+ ```ts
29
+ new Event3D({
30
+ hitArea: { type: 'box', width: 1, height: 2, depth: 1 },
31
+ })
32
+ ```
25
33
 
26
34
  ### Events emitted by the `Event3D` component
27
35
 
@@ -4,7 +4,7 @@
4
4
  "category": "input",
5
5
  "dimension": "3d",
6
6
  "isCore": false,
7
- "keywords": ["3d", "pointer", "touch", "tap", "raycast", "input", "event"],
7
+ "keywords": ["3d", "pointer", "touch", "tap", "raycast", "input", "event", "hitArea"],
8
8
  "agentSkill": "./agent-skill.md",
9
9
  "requires": ["@combos-fun/engine", "@combos-fun/plugin-renderer-3d"],
10
10
  "exports": ["Event3DSystem", "Event3D"]
@@ -29,6 +29,7 @@ let Event3DSystem = class Event3DSystem extends pluginRenderer3d.Renderer3D {
29
29
  this.ndc = new three.Vector2();
30
30
  this.localScratch = new three.Vector3();
31
31
  this.downByPointer = new Map();
32
+ this.hitAreas = new Map();
32
33
  this.canvas = null;
33
34
  this.onPointerDown = (e) => this.handlePointer(e, 'touchstart');
34
35
  this.onPointerMove = (e) => this.handlePointer(e, 'touchmove');
@@ -50,7 +51,17 @@ let Event3DSystem = class Event3DSystem extends pluginRenderer3d.Renderer3D {
50
51
  componentChanged(changed) {
51
52
  if (changed.componentName !== 'Event3D')
52
53
  return;
54
+ const component = changed.component;
55
+ if (changed.type === engine.OBSERVER_TYPE.ADD) {
56
+ this.syncHitArea(changed.gameObject, component);
57
+ return;
58
+ }
59
+ if (changed.type === engine.OBSERVER_TYPE.CHANGE) {
60
+ this.syncHitArea(changed.gameObject, component);
61
+ return;
62
+ }
53
63
  if (changed.type === engine.OBSERVER_TYPE.REMOVE) {
64
+ this.removeHitArea(changed.gameObject.id);
54
65
  changed.component.removeAllListeners();
55
66
  for (const [pointerId, hit] of this.downByPointer) {
56
67
  if (hit.gameObject.id === changed.gameObject.id) {
@@ -59,6 +70,51 @@ let Event3DSystem = class Event3DSystem extends pluginRenderer3d.Renderer3D {
59
70
  }
60
71
  }
61
72
  }
73
+ syncHitArea(gameObject, component) {
74
+ this.removeHitArea(gameObject.id);
75
+ if (!component.hitArea)
76
+ return;
77
+ const mesh = this.createHitAreaMesh(component.hitArea);
78
+ if (!mesh)
79
+ return;
80
+ pluginRenderer3d.tagObject3D(mesh, gameObject.id);
81
+ mesh.name = '__hitArea';
82
+ this.threeContext.attachVisual(gameObject.id, mesh, gameObject);
83
+ this.hitAreas.set(gameObject.id, mesh);
84
+ }
85
+ createHitAreaMesh(hitArea) {
86
+ const type = String(hitArea.type || 'box').toLowerCase();
87
+ let geometry;
88
+ if (type === 'sphere') {
89
+ geometry = new three.SphereGeometry(hitArea.radius ?? 0.5, 16, 12);
90
+ }
91
+ else if (type === 'plane') {
92
+ geometry = new three.PlaneGeometry(hitArea.width ?? 1, hitArea.height ?? 1);
93
+ }
94
+ else if (type === 'box') {
95
+ geometry = new three.BoxGeometry(hitArea.width ?? 1, hitArea.height ?? 1, hitArea.depth ?? 1);
96
+ }
97
+ else {
98
+ return null;
99
+ }
100
+ const material = new three.MeshBasicMaterial({
101
+ transparent: true,
102
+ opacity: 0,
103
+ depthWrite: false,
104
+ });
105
+ const mesh = new three.Mesh(geometry, material);
106
+ mesh.visible = true;
107
+ return mesh;
108
+ }
109
+ removeHitArea(id) {
110
+ const mesh = this.hitAreas.get(id);
111
+ if (!mesh)
112
+ return;
113
+ this.threeContext.detachVisual(id, mesh);
114
+ mesh.geometry.dispose();
115
+ mesh.material.dispose();
116
+ this.hitAreas.delete(id);
117
+ }
62
118
  rendererUpdate(_gameObject) { }
63
119
  onDestroy() {
64
120
  if (!this.canvas)
@@ -70,6 +126,10 @@ let Event3DSystem = class Event3DSystem extends pluginRenderer3d.Renderer3D {
70
126
  this.canvas.removeEventListener('pointerleave', this.onPointerCancel);
71
127
  this.canvas = null;
72
128
  this.downByPointer.clear();
129
+ for (const [id] of this.hitAreas) {
130
+ this.removeHitArea(id);
131
+ }
132
+ this.hitAreas.clear();
73
133
  }
74
134
  handlePointer(e, kind) {
75
135
  const hit = this.hitFromEvent(e);
@@ -142,7 +202,7 @@ let Event3DSystem = class Event3DSystem extends pluginRenderer3d.Renderer3D {
142
202
  this.raycaster.setFromCamera(this.ndc, this.threeContext.camera);
143
203
  const intersections = this.raycaster.intersectObjects(this.threeContext.scene.children, true);
144
204
  for (const intersection of intersections) {
145
- const id = pluginRenderer3d.gameObjectIdFromObject3D(intersection.object);
205
+ const id = pluginRenderer3d.gameObjectIdFromIntersection(intersection);
146
206
  if (id == null)
147
207
  continue;
148
208
  const gameObject = this.game.gameObjects.find((go) => go.id === id);
@@ -164,7 +224,7 @@ let Event3DSystem = class Event3DSystem extends pluginRenderer3d.Renderer3D {
164
224
  };
165
225
  Event3DSystem = tslib.__decorate([
166
226
  engine.decorators.componentObserver({
167
- Event3D: [],
227
+ Event3D: [{ prop: ['hitArea'], deep: true }],
168
228
  })
169
229
  ], Event3DSystem);
170
230
  var Event3DSystem_default = Event3DSystem;
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-renderer-3d-event.cjs.js","sources":["../lib/component.ts","../lib/system.ts"],"sourcesContent":["import { Component } from '@combos-fun/engine';\nimport type { GameObject } from '@combos-fun/engine';\n\ntype TouchEventName = 'touchstart' | 'touchmove' | 'touchend' | 'tap' | 'touchendoutside' | 'touchcancel';\n\nexport type Event3DParam = {\n stopPropagation: () => void,\n data: {\n pointerId: number,\n position: {\n x: number,\n y: number,\n },\n localPosition: {\n x: number,\n y: number,\n z: number,\n },\n },\n gameObject: GameObject,\n};\n\nexport interface Event3DParams {}\n\nexport default class Event3D extends Component<Event3DParams> {\n static componentName = 'Event3D';\n\n init(params?: Event3DParams) {\n params && Object.assign(this, params);\n }\n\n emit(eventName: TouchEventName, ...args: [Event3DParam]): boolean\n emit<T extends string>(eventName: Exclude<T, TouchEventName>, ...args: any[]): boolean\n emit(en: string, ...args: any[]) {\n return super.emit(en, ...args);\n }\n\n once(eventName: TouchEventName, fn: (arg: Event3DParam) => void, context?: any): this\n once<T extends string>(eventName: Exclude<T, TouchEventName>, fn: (...args: any[]) => void, context?: any): this\n once(en: string, fn: (...args: any[]) => void, context?: any) {\n return super.once(en, fn, context);\n }\n\n on(eventName: TouchEventName, fn: (arg: Event3DParam) => void, context?: any): this\n on<T extends string>(eventName: Exclude<T, TouchEventName>, fn: (...args: any[]) => void, context?: any): this\n on(en: string, fn: (...args: any[]) => void, context?: any) {\n return super.on(en, fn, context);\n }\n}\n","import { decorators, ComponentChanged, OBSERVER_TYPE, GameObject } from '@combos-fun/engine';\nimport {\n Renderer3D,\n Renderer3DSystem,\n gameObjectIdFromObject3D,\n} from '@combos-fun/plugin-renderer-3d';\nimport { Raycaster, Vector2, Vector3 } from 'three';\nimport Event3D from './component';\n\nexport interface Event3DSystemParams {}\n\ninterface PointerHit {\n gameObject: GameObject;\n component: Event3D;\n local: Vector3;\n}\n\n@decorators.componentObserver({\n Event3D: [],\n})\nexport default class Event3DSystem extends Renderer3D {\n static systemName = 'Event3DSystem';\n name: string = 'Event3DSystem';\n\n private raycaster = new Raycaster();\n private ndc = new Vector2();\n private localScratch = new Vector3();\n private downByPointer = new Map<number, PointerHit>();\n private canvas: HTMLCanvasElement | null = null;\n\n private onPointerDown = (e: PointerEvent) => this.handlePointer(e, 'touchstart');\n private onPointerMove = (e: PointerEvent) => this.handlePointer(e, 'touchmove');\n private onPointerUp = (e: PointerEvent) => this.handlePointer(e, 'touchend');\n private onPointerCancel = (e: PointerEvent) => this.handlePointer(e, 'touchcancel');\n\n init(_params?: Event3DSystemParams) {\n const renderer3DSystem = this.game.getSystem(Renderer3DSystem) as Renderer3DSystem;\n renderer3DSystem.rendererManager.register(this);\n\n this.canvas = this.threeContext.renderer.domElement;\n this.canvas.style.touchAction = 'none';\n this.canvas.addEventListener('pointerdown', this.onPointerDown);\n this.canvas.addEventListener('pointermove', this.onPointerMove);\n this.canvas.addEventListener('pointerup', this.onPointerUp);\n this.canvas.addEventListener('pointercancel', this.onPointerCancel);\n this.canvas.addEventListener('pointerleave', this.onPointerCancel);\n }\n\n componentChanged(changed: ComponentChanged) {\n if (changed.componentName !== 'Event3D') return;\n if (changed.type === OBSERVER_TYPE.REMOVE) {\n changed.component.removeAllListeners();\n for (const [pointerId, hit] of this.downByPointer) {\n if (hit.gameObject.id === changed.gameObject.id) {\n this.downByPointer.delete(pointerId);\n }\n }\n }\n }\n\n rendererUpdate(_gameObject: GameObject) {}\n\n onDestroy() {\n if (!this.canvas) return;\n this.canvas.removeEventListener('pointerdown', this.onPointerDown);\n this.canvas.removeEventListener('pointermove', this.onPointerMove);\n this.canvas.removeEventListener('pointerup', this.onPointerUp);\n this.canvas.removeEventListener('pointercancel', this.onPointerCancel);\n this.canvas.removeEventListener('pointerleave', this.onPointerCancel);\n this.canvas = null;\n this.downByPointer.clear();\n }\n\n private handlePointer(e: PointerEvent, kind: 'touchstart' | 'touchmove' | 'touchend' | 'touchcancel') {\n const hit = this.hitFromEvent(e);\n const canvasPos = this.canvasPosition(e);\n\n if (kind === 'touchstart') {\n if (!hit) return;\n this.downByPointer.set(e.pointerId, hit);\n this.emitOn(hit, 'touchstart', e, canvasPos);\n return;\n }\n\n if (kind === 'touchmove') {\n if (!hit) return;\n this.emitOn(hit, 'touchmove', e, canvasPos);\n return;\n }\n\n const down = this.downByPointer.get(e.pointerId);\n this.downByPointer.delete(e.pointerId);\n\n if (kind === 'touchcancel') {\n if (down) this.emitOn(down, 'touchcancel', e, canvasPos);\n return;\n }\n\n if (hit && down && hit.gameObject.id === down.gameObject.id) {\n this.emitOn(hit, 'touchend', e, canvasPos);\n this.emitOn(hit, 'tap', e, canvasPos);\n return;\n }\n\n if (down) {\n this.emitOn(down, 'touchendoutside', e, canvasPos);\n }\n if (hit) {\n this.emitOn(hit, 'touchend', e, canvasPos);\n }\n }\n\n private emitOn(\n hit: PointerHit,\n eventName: 'touchstart' | 'touchmove' | 'touchend' | 'tap' | 'touchendoutside' | 'touchcancel',\n e: PointerEvent,\n canvasPos: { x: number; y: number },\n ) {\n let stopped = false;\n hit.component.emit(eventName, {\n stopPropagation: () => { stopped = true; },\n data: {\n pointerId: e.pointerId,\n position: canvasPos,\n localPosition: {\n x: hit.local.x,\n y: hit.local.y,\n z: hit.local.z,\n },\n },\n gameObject: hit.gameObject,\n });\n if (stopped) {\n e.stopPropagation();\n }\n }\n\n private canvasPosition(e: PointerEvent) {\n const rect = this.canvas.getBoundingClientRect();\n return {\n x: e.clientX - rect.left,\n y: e.clientY - rect.top,\n };\n }\n\n private hitFromEvent(e: PointerEvent): PointerHit | null {\n if (!this.canvas) return null;\n const rect = this.canvas.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) return null;\n\n this.ndc.set(\n ((e.clientX - rect.left) / rect.width) * 2 - 1,\n -((e.clientY - rect.top) / rect.height) * 2 + 1,\n );\n this.raycaster.setFromCamera(this.ndc, this.threeContext.camera);\n const intersections = this.raycaster.intersectObjects(this.threeContext.scene.children, true);\n\n for (const intersection of intersections) {\n const id = gameObjectIdFromObject3D(intersection.object);\n if (id == null) continue;\n const gameObject = this.game.gameObjects.find((go) => go.id === id);\n if (!gameObject) continue;\n const component = gameObject.getComponent(Event3D) as Event3D | undefined;\n if (!component) continue;\n\n this.localScratch.copy(intersection.point);\n intersection.object.worldToLocal(this.localScratch);\n return {\n gameObject,\n component,\n local: this.localScratch.clone(),\n };\n }\n return null;\n }\n}\n"],"names":["Component","Renderer3D","Raycaster","Vector2","Vector3","Renderer3DSystem","OBSERVER_TYPE","gameObjectIdFromObject3D","__decorate","decorators"],"mappings":"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"}
1
+ {"version":3,"file":"plugin-renderer-3d-event.cjs.js","sources":["../lib/component.ts","../lib/system.ts"],"sourcesContent":["import { Component } from '@combos-fun/engine';\nimport type { GameObject } from '@combos-fun/engine';\n\ntype TouchEventName = 'touchstart' | 'touchmove' | 'touchend' | 'tap' | 'touchendoutside' | 'touchcancel';\n\nexport type Event3DHitAreaType = 'box' | 'sphere' | 'plane';\n\nexport interface Event3DHitArea {\n type: Event3DHitAreaType | string;\n width?: number;\n height?: number;\n depth?: number;\n radius?: number;\n}\n\nexport type Event3DParam = {\n stopPropagation: () => void,\n data: {\n pointerId: number,\n position: {\n x: number,\n y: number,\n },\n localPosition: {\n x: number,\n y: number,\n z: number,\n },\n },\n gameObject: GameObject,\n};\n\nexport interface Event3DParams {\n hitArea?: Event3DHitArea;\n}\n\nexport default class Event3D extends Component<Event3DParams> {\n static componentName = 'Event3D';\n\n hitArea?: Event3DHitArea;\n\n init(params?: Event3DParams) {\n params && Object.assign(this, params);\n }\n\n emit(eventName: TouchEventName, ...args: [Event3DParam]): boolean\n emit<T extends string>(eventName: Exclude<T, TouchEventName>, ...args: any[]): boolean\n emit(en: string, ...args: any[]) {\n return super.emit(en, ...args);\n }\n\n once(eventName: TouchEventName, fn: (arg: Event3DParam) => void, context?: any): this\n once<T extends string>(eventName: Exclude<T, TouchEventName>, fn: (...args: any[]) => void, context?: any): this\n once(en: string, fn: (...args: any[]) => void, context?: any) {\n return super.once(en, fn, context);\n }\n\n on(eventName: TouchEventName, fn: (arg: Event3DParam) => void, context?: any): this\n on<T extends string>(eventName: Exclude<T, TouchEventName>, fn: (...args: any[]) => void, context?: any): this\n on(en: string, fn: (...args: any[]) => void, context?: any) {\n return super.on(en, fn, context);\n }\n}\n","import { decorators, ComponentChanged, OBSERVER_TYPE, GameObject } from '@combos-fun/engine';\nimport {\n Renderer3D,\n Renderer3DSystem,\n gameObjectIdFromIntersection,\n tagObject3D,\n} from '@combos-fun/plugin-renderer-3d';\nimport {\n BoxGeometry,\n Mesh,\n MeshBasicMaterial,\n PlaneGeometry,\n Raycaster,\n SphereGeometry,\n Vector2,\n Vector3,\n} from 'three';\nimport Event3D from './component';\nimport type { Event3DHitArea } from './component';\n\nexport interface Event3DSystemParams {}\n\ninterface PointerHit {\n gameObject: GameObject;\n component: Event3D;\n local: Vector3;\n}\n\n@decorators.componentObserver({\n Event3D: [{ prop: ['hitArea'], deep: true }],\n})\nexport default class Event3DSystem extends Renderer3D {\n static systemName = 'Event3DSystem';\n name: string = 'Event3DSystem';\n\n private raycaster = new Raycaster();\n private ndc = new Vector2();\n private localScratch = new Vector3();\n private downByPointer = new Map<number, PointerHit>();\n private hitAreas = new Map<number, Mesh>();\n private canvas: HTMLCanvasElement | null = null;\n\n private onPointerDown = (e: PointerEvent) => this.handlePointer(e, 'touchstart');\n private onPointerMove = (e: PointerEvent) => this.handlePointer(e, 'touchmove');\n private onPointerUp = (e: PointerEvent) => this.handlePointer(e, 'touchend');\n private onPointerCancel = (e: PointerEvent) => this.handlePointer(e, 'touchcancel');\n\n init(_params?: Event3DSystemParams) {\n const renderer3DSystem = this.game.getSystem(Renderer3DSystem) as Renderer3DSystem;\n renderer3DSystem.rendererManager.register(this);\n\n this.canvas = this.threeContext.renderer.domElement;\n this.canvas.style.touchAction = 'none';\n this.canvas.addEventListener('pointerdown', this.onPointerDown);\n this.canvas.addEventListener('pointermove', this.onPointerMove);\n this.canvas.addEventListener('pointerup', this.onPointerUp);\n this.canvas.addEventListener('pointercancel', this.onPointerCancel);\n this.canvas.addEventListener('pointerleave', this.onPointerCancel);\n }\n\n componentChanged(changed: ComponentChanged) {\n if (changed.componentName !== 'Event3D') return;\n const component = changed.component as Event3D;\n if (changed.type === OBSERVER_TYPE.ADD) {\n this.syncHitArea(changed.gameObject, component);\n return;\n }\n if (changed.type === OBSERVER_TYPE.CHANGE) {\n this.syncHitArea(changed.gameObject, component);\n return;\n }\n if (changed.type === OBSERVER_TYPE.REMOVE) {\n this.removeHitArea(changed.gameObject.id);\n changed.component.removeAllListeners();\n for (const [pointerId, hit] of this.downByPointer) {\n if (hit.gameObject.id === changed.gameObject.id) {\n this.downByPointer.delete(pointerId);\n }\n }\n }\n }\n\n private syncHitArea(gameObject: GameObject, component: Event3D) {\n this.removeHitArea(gameObject.id);\n if (!component.hitArea) return;\n const mesh = this.createHitAreaMesh(component.hitArea);\n if (!mesh) return;\n tagObject3D(mesh, gameObject.id);\n mesh.name = '__hitArea';\n this.threeContext.attachVisual(gameObject.id, mesh, gameObject);\n this.hitAreas.set(gameObject.id, mesh);\n }\n\n private createHitAreaMesh(hitArea: Event3DHitArea): Mesh | null {\n const type = String(hitArea.type || 'box').toLowerCase();\n let geometry;\n if (type === 'sphere') {\n geometry = new SphereGeometry(hitArea.radius ?? 0.5, 16, 12);\n } else if (type === 'plane') {\n geometry = new PlaneGeometry(hitArea.width ?? 1, hitArea.height ?? 1);\n } else if (type === 'box') {\n geometry = new BoxGeometry(hitArea.width ?? 1, hitArea.height ?? 1, hitArea.depth ?? 1);\n } else {\n return null;\n }\n const material = new MeshBasicMaterial({\n transparent: true,\n opacity: 0,\n depthWrite: false,\n });\n const mesh = new Mesh(geometry, material);\n mesh.visible = true;\n return mesh;\n }\n\n private removeHitArea(id: number) {\n const mesh = this.hitAreas.get(id);\n if (!mesh) return;\n this.threeContext.detachVisual(id, mesh);\n mesh.geometry.dispose();\n (mesh.material as MeshBasicMaterial).dispose();\n this.hitAreas.delete(id);\n }\n\n rendererUpdate(_gameObject: GameObject) {}\n\n onDestroy() {\n if (!this.canvas) return;\n this.canvas.removeEventListener('pointerdown', this.onPointerDown);\n this.canvas.removeEventListener('pointermove', this.onPointerMove);\n this.canvas.removeEventListener('pointerup', this.onPointerUp);\n this.canvas.removeEventListener('pointercancel', this.onPointerCancel);\n this.canvas.removeEventListener('pointerleave', this.onPointerCancel);\n this.canvas = null;\n this.downByPointer.clear();\n for (const [id] of this.hitAreas) {\n this.removeHitArea(id);\n }\n this.hitAreas.clear();\n }\n\n private handlePointer(e: PointerEvent, kind: 'touchstart' | 'touchmove' | 'touchend' | 'touchcancel') {\n const hit = this.hitFromEvent(e);\n const canvasPos = this.canvasPosition(e);\n\n if (kind === 'touchstart') {\n if (!hit) return;\n this.downByPointer.set(e.pointerId, hit);\n this.emitOn(hit, 'touchstart', e, canvasPos);\n return;\n }\n\n if (kind === 'touchmove') {\n if (!hit) return;\n this.emitOn(hit, 'touchmove', e, canvasPos);\n return;\n }\n\n const down = this.downByPointer.get(e.pointerId);\n this.downByPointer.delete(e.pointerId);\n\n if (kind === 'touchcancel') {\n if (down) this.emitOn(down, 'touchcancel', e, canvasPos);\n return;\n }\n\n if (hit && down && hit.gameObject.id === down.gameObject.id) {\n this.emitOn(hit, 'touchend', e, canvasPos);\n this.emitOn(hit, 'tap', e, canvasPos);\n return;\n }\n\n if (down) {\n this.emitOn(down, 'touchendoutside', e, canvasPos);\n }\n if (hit) {\n this.emitOn(hit, 'touchend', e, canvasPos);\n }\n }\n\n private emitOn(\n hit: PointerHit,\n eventName: 'touchstart' | 'touchmove' | 'touchend' | 'tap' | 'touchendoutside' | 'touchcancel',\n e: PointerEvent,\n canvasPos: { x: number; y: number },\n ) {\n let stopped = false;\n hit.component.emit(eventName, {\n stopPropagation: () => { stopped = true; },\n data: {\n pointerId: e.pointerId,\n position: canvasPos,\n localPosition: {\n x: hit.local.x,\n y: hit.local.y,\n z: hit.local.z,\n },\n },\n gameObject: hit.gameObject,\n });\n if (stopped) {\n e.stopPropagation();\n }\n }\n\n private canvasPosition(e: PointerEvent) {\n const rect = this.canvas.getBoundingClientRect();\n return {\n x: e.clientX - rect.left,\n y: e.clientY - rect.top,\n };\n }\n\n private hitFromEvent(e: PointerEvent): PointerHit | null {\n if (!this.canvas) return null;\n const rect = this.canvas.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) return null;\n\n this.ndc.set(\n ((e.clientX - rect.left) / rect.width) * 2 - 1,\n -((e.clientY - rect.top) / rect.height) * 2 + 1,\n );\n this.raycaster.setFromCamera(this.ndc, this.threeContext.camera);\n const intersections = this.raycaster.intersectObjects(this.threeContext.scene.children, true);\n\n for (const intersection of intersections) {\n const id = gameObjectIdFromIntersection(intersection);\n if (id == null) continue;\n const gameObject = this.game.gameObjects.find((go) => go.id === id);\n if (!gameObject) continue;\n const component = gameObject.getComponent(Event3D) as Event3D | undefined;\n if (!component) continue;\n\n this.localScratch.copy(intersection.point);\n intersection.object.worldToLocal(this.localScratch);\n return {\n gameObject,\n component,\n local: this.localScratch.clone(),\n };\n }\n return null;\n }\n}\n"],"names":["Component","Renderer3D","Raycaster","Vector2","Vector3","Renderer3DSystem","OBSERVER_TYPE","tagObject3D","SphereGeometry","PlaneGeometry","BoxGeometry","MeshBasicMaterial","Mesh","gameObjectIdFromIntersection","__decorate","decorators"],"mappings":"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"}
@@ -1 +1 @@
1
- "use strict";var t=require("tslib"),e=require("@combos-fun/engine"),n=require("@combos-fun/plugin-renderer-3d"),i=require("three");class o extends e.Component{static{this.componentName="Event3D"}init(t){t&&Object.assign(this,t)}emit(t,...e){return super.emit(t,...e)}once(t,e,n){return super.once(t,e,n)}on(t,e,n){return super.on(t,e,n)}}let s=class extends n.Renderer3D{constructor(){super(...arguments),this.name="Event3DSystem",this.raycaster=new i.Raycaster,this.ndc=new i.Vector2,this.localScratch=new i.Vector3,this.downByPointer=new Map,this.canvas=null,this.onPointerDown=t=>this.handlePointer(t,"touchstart"),this.onPointerMove=t=>this.handlePointer(t,"touchmove"),this.onPointerUp=t=>this.handlePointer(t,"touchend"),this.onPointerCancel=t=>this.handlePointer(t,"touchcancel")}static{this.systemName="Event3DSystem"}init(t){this.game.getSystem(n.Renderer3DSystem).rendererManager.register(this),this.canvas=this.threeContext.renderer.domElement,this.canvas.style.touchAction="none",this.canvas.addEventListener("pointerdown",this.onPointerDown),this.canvas.addEventListener("pointermove",this.onPointerMove),this.canvas.addEventListener("pointerup",this.onPointerUp),this.canvas.addEventListener("pointercancel",this.onPointerCancel),this.canvas.addEventListener("pointerleave",this.onPointerCancel)}componentChanged(t){if("Event3D"===t.componentName&&t.type===e.OBSERVER_TYPE.REMOVE){t.component.removeAllListeners();for(const[e,n]of this.downByPointer)n.gameObject.id===t.gameObject.id&&this.downByPointer.delete(e)}}rendererUpdate(t){}onDestroy(){this.canvas&&(this.canvas.removeEventListener("pointerdown",this.onPointerDown),this.canvas.removeEventListener("pointermove",this.onPointerMove),this.canvas.removeEventListener("pointerup",this.onPointerUp),this.canvas.removeEventListener("pointercancel",this.onPointerCancel),this.canvas.removeEventListener("pointerleave",this.onPointerCancel),this.canvas=null,this.downByPointer.clear())}handlePointer(t,e){const n=this.hitFromEvent(t),i=this.canvasPosition(t);if("touchstart"===e){if(!n)return;return this.downByPointer.set(t.pointerId,n),void this.emitOn(n,"touchstart",t,i)}if("touchmove"===e){if(!n)return;return void this.emitOn(n,"touchmove",t,i)}const o=this.downByPointer.get(t.pointerId);if(this.downByPointer.delete(t.pointerId),"touchcancel"!==e){if(n&&o&&n.gameObject.id===o.gameObject.id)return this.emitOn(n,"touchend",t,i),void this.emitOn(n,"tap",t,i);o&&this.emitOn(o,"touchendoutside",t,i),n&&this.emitOn(n,"touchend",t,i)}else o&&this.emitOn(o,"touchcancel",t,i)}emitOn(t,e,n,i){let o=!1;t.component.emit(e,{stopPropagation:()=>{o=!0},data:{pointerId:n.pointerId,position:i,localPosition:{x:t.local.x,y:t.local.y,z:t.local.z}},gameObject:t.gameObject}),o&&n.stopPropagation()}canvasPosition(t){const e=this.canvas.getBoundingClientRect();return{x:t.clientX-e.left,y:t.clientY-e.top}}hitFromEvent(t){if(!this.canvas)return null;const e=this.canvas.getBoundingClientRect();if(0===e.width||0===e.height)return null;this.ndc.set((t.clientX-e.left)/e.width*2-1,-(t.clientY-e.top)/e.height*2+1),this.raycaster.setFromCamera(this.ndc,this.threeContext.camera);const i=this.raycaster.intersectObjects(this.threeContext.scene.children,!0);for(const t of i){const e=n.gameObjectIdFromObject3D(t.object);if(null==e)continue;const i=this.game.gameObjects.find(t=>t.id===e);if(!i)continue;const s=i.getComponent(o);if(s)return this.localScratch.copy(t.point),t.object.worldToLocal(this.localScratch),{gameObject:i,component:s,local:this.localScratch.clone()}}return null}};s=t.__decorate([e.decorators.componentObserver({Event3D:[]})],s);var r=s;exports.Event3D=o,exports.Event3DSystem=r;
1
+ "use strict";var e=require("tslib"),t=require("@combos-fun/engine"),n=require("@combos-fun/plugin-renderer-3d"),i=require("three");class o extends t.Component{static{this.componentName="Event3D"}init(e){e&&Object.assign(this,e)}emit(e,...t){return super.emit(e,...t)}once(e,t,n){return super.once(e,t,n)}on(e,t,n){return super.on(e,t,n)}}let s=class extends n.Renderer3D{constructor(){super(...arguments),this.name="Event3DSystem",this.raycaster=new i.Raycaster,this.ndc=new i.Vector2,this.localScratch=new i.Vector3,this.downByPointer=new Map,this.hitAreas=new Map,this.canvas=null,this.onPointerDown=e=>this.handlePointer(e,"touchstart"),this.onPointerMove=e=>this.handlePointer(e,"touchmove"),this.onPointerUp=e=>this.handlePointer(e,"touchend"),this.onPointerCancel=e=>this.handlePointer(e,"touchcancel")}static{this.systemName="Event3DSystem"}init(e){this.game.getSystem(n.Renderer3DSystem).rendererManager.register(this),this.canvas=this.threeContext.renderer.domElement,this.canvas.style.touchAction="none",this.canvas.addEventListener("pointerdown",this.onPointerDown),this.canvas.addEventListener("pointermove",this.onPointerMove),this.canvas.addEventListener("pointerup",this.onPointerUp),this.canvas.addEventListener("pointercancel",this.onPointerCancel),this.canvas.addEventListener("pointerleave",this.onPointerCancel)}componentChanged(e){if("Event3D"!==e.componentName)return;const n=e.component;if(e.type!==t.OBSERVER_TYPE.ADD)if(e.type!==t.OBSERVER_TYPE.CHANGE){if(e.type===t.OBSERVER_TYPE.REMOVE){this.removeHitArea(e.gameObject.id),e.component.removeAllListeners();for(const[t,n]of this.downByPointer)n.gameObject.id===e.gameObject.id&&this.downByPointer.delete(t)}}else this.syncHitArea(e.gameObject,n);else this.syncHitArea(e.gameObject,n)}syncHitArea(e,t){if(this.removeHitArea(e.id),!t.hitArea)return;const i=this.createHitAreaMesh(t.hitArea);i&&(n.tagObject3D(i,e.id),i.name="__hitArea",this.threeContext.attachVisual(e.id,i,e),this.hitAreas.set(e.id,i))}createHitAreaMesh(e){const t=String(e.type||"box").toLowerCase();let n;if("sphere"===t)n=new i.SphereGeometry(e.radius??.5,16,12);else if("plane"===t)n=new i.PlaneGeometry(e.width??1,e.height??1);else{if("box"!==t)return null;n=new i.BoxGeometry(e.width??1,e.height??1,e.depth??1)}const o=new i.MeshBasicMaterial({transparent:!0,opacity:0,depthWrite:!1}),s=new i.Mesh(n,o);return s.visible=!0,s}removeHitArea(e){const t=this.hitAreas.get(e);t&&(this.threeContext.detachVisual(e,t),t.geometry.dispose(),t.material.dispose(),this.hitAreas.delete(e))}rendererUpdate(e){}onDestroy(){if(this.canvas){this.canvas.removeEventListener("pointerdown",this.onPointerDown),this.canvas.removeEventListener("pointermove",this.onPointerMove),this.canvas.removeEventListener("pointerup",this.onPointerUp),this.canvas.removeEventListener("pointercancel",this.onPointerCancel),this.canvas.removeEventListener("pointerleave",this.onPointerCancel),this.canvas=null,this.downByPointer.clear();for(const[e]of this.hitAreas)this.removeHitArea(e);this.hitAreas.clear()}}handlePointer(e,t){const n=this.hitFromEvent(e),i=this.canvasPosition(e);if("touchstart"===t){if(!n)return;return this.downByPointer.set(e.pointerId,n),void this.emitOn(n,"touchstart",e,i)}if("touchmove"===t){if(!n)return;return void this.emitOn(n,"touchmove",e,i)}const o=this.downByPointer.get(e.pointerId);if(this.downByPointer.delete(e.pointerId),"touchcancel"!==t){if(n&&o&&n.gameObject.id===o.gameObject.id)return this.emitOn(n,"touchend",e,i),void this.emitOn(n,"tap",e,i);o&&this.emitOn(o,"touchendoutside",e,i),n&&this.emitOn(n,"touchend",e,i)}else o&&this.emitOn(o,"touchcancel",e,i)}emitOn(e,t,n,i){let o=!1;e.component.emit(t,{stopPropagation:()=>{o=!0},data:{pointerId:n.pointerId,position:i,localPosition:{x:e.local.x,y:e.local.y,z:e.local.z}},gameObject:e.gameObject}),o&&n.stopPropagation()}canvasPosition(e){const t=this.canvas.getBoundingClientRect();return{x:e.clientX-t.left,y:e.clientY-t.top}}hitFromEvent(e){if(!this.canvas)return null;const t=this.canvas.getBoundingClientRect();if(0===t.width||0===t.height)return null;this.ndc.set((e.clientX-t.left)/t.width*2-1,-(e.clientY-t.top)/t.height*2+1),this.raycaster.setFromCamera(this.ndc,this.threeContext.camera);const i=this.raycaster.intersectObjects(this.threeContext.scene.children,!0);for(const e of i){const t=n.gameObjectIdFromIntersection(e);if(null==t)continue;const i=this.game.gameObjects.find(e=>e.id===t);if(!i)continue;const s=i.getComponent(o);if(s)return this.localScratch.copy(e.point),e.object.worldToLocal(this.localScratch),{gameObject:i,component:s,local:this.localScratch.clone()}}return null}};s=e.__decorate([t.decorators.componentObserver({Event3D:[{prop:["hitArea"],deep:!0}]})],s);var r=s;exports.Event3D=o,exports.Event3DSystem=r;
@@ -10,6 +10,7 @@ declare class Event3DSystem extends Renderer3D {
10
10
  private ndc;
11
11
  private localScratch;
12
12
  private downByPointer;
13
+ private hitAreas;
13
14
  private canvas;
14
15
  private onPointerDown;
15
16
  private onPointerMove;
@@ -17,6 +18,9 @@ declare class Event3DSystem extends Renderer3D {
17
18
  private onPointerCancel;
18
19
  init(_params?: Event3DSystemParams): void;
19
20
  componentChanged(changed: ComponentChanged): void;
21
+ private syncHitArea;
22
+ private createHitAreaMesh;
23
+ private removeHitArea;
20
24
  rendererUpdate(_gameObject: GameObject): void;
21
25
  onDestroy(): void;
22
26
  private handlePointer;
@@ -26,6 +30,14 @@ declare class Event3DSystem extends Renderer3D {
26
30
  }
27
31
 
28
32
  type TouchEventName = 'touchstart' | 'touchmove' | 'touchend' | 'tap' | 'touchendoutside' | 'touchcancel';
33
+ type Event3DHitAreaType = 'box' | 'sphere' | 'plane';
34
+ interface Event3DHitArea {
35
+ type: Event3DHitAreaType | string;
36
+ width?: number;
37
+ height?: number;
38
+ depth?: number;
39
+ radius?: number;
40
+ }
29
41
  type Event3DParam = {
30
42
  stopPropagation: () => void;
31
43
  data: {
@@ -43,9 +55,11 @@ type Event3DParam = {
43
55
  gameObject: GameObject;
44
56
  };
45
57
  interface Event3DParams {
58
+ hitArea?: Event3DHitArea;
46
59
  }
47
60
  declare class Event3D extends Component<Event3DParams> {
48
61
  static componentName: string;
62
+ hitArea?: Event3DHitArea;
49
63
  init(params?: Event3DParams): void;
50
64
  emit(eventName: TouchEventName, ...args: [Event3DParam]): boolean;
51
65
  emit<T extends string>(eventName: Exclude<T, TouchEventName>, ...args: any[]): boolean;
@@ -56,4 +70,4 @@ declare class Event3D extends Component<Event3DParams> {
56
70
  }
57
71
 
58
72
  export { Event3D, Event3DSystem };
59
- export type { Event3DParam, Event3DParams, Event3DSystemParams };
73
+ export type { Event3DHitArea, Event3DHitAreaType, Event3DParam, Event3DParams, Event3DSystemParams };
@@ -1,7 +1,7 @@
1
1
  import { __decorate } from 'tslib';
2
2
  import { Component, OBSERVER_TYPE, decorators } from '@combos-fun/engine';
3
- import { Renderer3D, Renderer3DSystem, gameObjectIdFromObject3D } from '@combos-fun/plugin-renderer-3d';
4
- import { Raycaster, Vector2, Vector3 } from 'three';
3
+ import { Renderer3D, Renderer3DSystem, tagObject3D, gameObjectIdFromIntersection } from '@combos-fun/plugin-renderer-3d';
4
+ import { Raycaster, Vector2, Vector3, SphereGeometry, PlaneGeometry, BoxGeometry, MeshBasicMaterial, Mesh } from 'three';
5
5
 
6
6
  class Event3D extends Component {
7
7
  static { this.componentName = 'Event3D'; }
@@ -27,6 +27,7 @@ let Event3DSystem = class Event3DSystem extends Renderer3D {
27
27
  this.ndc = new Vector2();
28
28
  this.localScratch = new Vector3();
29
29
  this.downByPointer = new Map();
30
+ this.hitAreas = new Map();
30
31
  this.canvas = null;
31
32
  this.onPointerDown = (e) => this.handlePointer(e, 'touchstart');
32
33
  this.onPointerMove = (e) => this.handlePointer(e, 'touchmove');
@@ -48,7 +49,17 @@ let Event3DSystem = class Event3DSystem extends Renderer3D {
48
49
  componentChanged(changed) {
49
50
  if (changed.componentName !== 'Event3D')
50
51
  return;
52
+ const component = changed.component;
53
+ if (changed.type === OBSERVER_TYPE.ADD) {
54
+ this.syncHitArea(changed.gameObject, component);
55
+ return;
56
+ }
57
+ if (changed.type === OBSERVER_TYPE.CHANGE) {
58
+ this.syncHitArea(changed.gameObject, component);
59
+ return;
60
+ }
51
61
  if (changed.type === OBSERVER_TYPE.REMOVE) {
62
+ this.removeHitArea(changed.gameObject.id);
52
63
  changed.component.removeAllListeners();
53
64
  for (const [pointerId, hit] of this.downByPointer) {
54
65
  if (hit.gameObject.id === changed.gameObject.id) {
@@ -57,6 +68,51 @@ let Event3DSystem = class Event3DSystem extends Renderer3D {
57
68
  }
58
69
  }
59
70
  }
71
+ syncHitArea(gameObject, component) {
72
+ this.removeHitArea(gameObject.id);
73
+ if (!component.hitArea)
74
+ return;
75
+ const mesh = this.createHitAreaMesh(component.hitArea);
76
+ if (!mesh)
77
+ return;
78
+ tagObject3D(mesh, gameObject.id);
79
+ mesh.name = '__hitArea';
80
+ this.threeContext.attachVisual(gameObject.id, mesh, gameObject);
81
+ this.hitAreas.set(gameObject.id, mesh);
82
+ }
83
+ createHitAreaMesh(hitArea) {
84
+ const type = String(hitArea.type || 'box').toLowerCase();
85
+ let geometry;
86
+ if (type === 'sphere') {
87
+ geometry = new SphereGeometry(hitArea.radius ?? 0.5, 16, 12);
88
+ }
89
+ else if (type === 'plane') {
90
+ geometry = new PlaneGeometry(hitArea.width ?? 1, hitArea.height ?? 1);
91
+ }
92
+ else if (type === 'box') {
93
+ geometry = new BoxGeometry(hitArea.width ?? 1, hitArea.height ?? 1, hitArea.depth ?? 1);
94
+ }
95
+ else {
96
+ return null;
97
+ }
98
+ const material = new MeshBasicMaterial({
99
+ transparent: true,
100
+ opacity: 0,
101
+ depthWrite: false,
102
+ });
103
+ const mesh = new Mesh(geometry, material);
104
+ mesh.visible = true;
105
+ return mesh;
106
+ }
107
+ removeHitArea(id) {
108
+ const mesh = this.hitAreas.get(id);
109
+ if (!mesh)
110
+ return;
111
+ this.threeContext.detachVisual(id, mesh);
112
+ mesh.geometry.dispose();
113
+ mesh.material.dispose();
114
+ this.hitAreas.delete(id);
115
+ }
60
116
  rendererUpdate(_gameObject) { }
61
117
  onDestroy() {
62
118
  if (!this.canvas)
@@ -68,6 +124,10 @@ let Event3DSystem = class Event3DSystem extends Renderer3D {
68
124
  this.canvas.removeEventListener('pointerleave', this.onPointerCancel);
69
125
  this.canvas = null;
70
126
  this.downByPointer.clear();
127
+ for (const [id] of this.hitAreas) {
128
+ this.removeHitArea(id);
129
+ }
130
+ this.hitAreas.clear();
71
131
  }
72
132
  handlePointer(e, kind) {
73
133
  const hit = this.hitFromEvent(e);
@@ -140,7 +200,7 @@ let Event3DSystem = class Event3DSystem extends Renderer3D {
140
200
  this.raycaster.setFromCamera(this.ndc, this.threeContext.camera);
141
201
  const intersections = this.raycaster.intersectObjects(this.threeContext.scene.children, true);
142
202
  for (const intersection of intersections) {
143
- const id = gameObjectIdFromObject3D(intersection.object);
203
+ const id = gameObjectIdFromIntersection(intersection);
144
204
  if (id == null)
145
205
  continue;
146
206
  const gameObject = this.game.gameObjects.find((go) => go.id === id);
@@ -162,7 +222,7 @@ let Event3DSystem = class Event3DSystem extends Renderer3D {
162
222
  };
163
223
  Event3DSystem = __decorate([
164
224
  decorators.componentObserver({
165
- Event3D: [],
225
+ Event3D: [{ prop: ['hitArea'], deep: true }],
166
226
  })
167
227
  ], Event3DSystem);
168
228
  var Event3DSystem_default = Event3DSystem;
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-renderer-3d-event.esm.js","sources":["../lib/component.ts","../lib/system.ts"],"sourcesContent":["import { Component } from '@combos-fun/engine';\nimport type { GameObject } from '@combos-fun/engine';\n\ntype TouchEventName = 'touchstart' | 'touchmove' | 'touchend' | 'tap' | 'touchendoutside' | 'touchcancel';\n\nexport type Event3DParam = {\n stopPropagation: () => void,\n data: {\n pointerId: number,\n position: {\n x: number,\n y: number,\n },\n localPosition: {\n x: number,\n y: number,\n z: number,\n },\n },\n gameObject: GameObject,\n};\n\nexport interface Event3DParams {}\n\nexport default class Event3D extends Component<Event3DParams> {\n static componentName = 'Event3D';\n\n init(params?: Event3DParams) {\n params && Object.assign(this, params);\n }\n\n emit(eventName: TouchEventName, ...args: [Event3DParam]): boolean\n emit<T extends string>(eventName: Exclude<T, TouchEventName>, ...args: any[]): boolean\n emit(en: string, ...args: any[]) {\n return super.emit(en, ...args);\n }\n\n once(eventName: TouchEventName, fn: (arg: Event3DParam) => void, context?: any): this\n once<T extends string>(eventName: Exclude<T, TouchEventName>, fn: (...args: any[]) => void, context?: any): this\n once(en: string, fn: (...args: any[]) => void, context?: any) {\n return super.once(en, fn, context);\n }\n\n on(eventName: TouchEventName, fn: (arg: Event3DParam) => void, context?: any): this\n on<T extends string>(eventName: Exclude<T, TouchEventName>, fn: (...args: any[]) => void, context?: any): this\n on(en: string, fn: (...args: any[]) => void, context?: any) {\n return super.on(en, fn, context);\n }\n}\n","import { decorators, ComponentChanged, OBSERVER_TYPE, GameObject } from '@combos-fun/engine';\nimport {\n Renderer3D,\n Renderer3DSystem,\n gameObjectIdFromObject3D,\n} from '@combos-fun/plugin-renderer-3d';\nimport { Raycaster, Vector2, Vector3 } from 'three';\nimport Event3D from './component';\n\nexport interface Event3DSystemParams {}\n\ninterface PointerHit {\n gameObject: GameObject;\n component: Event3D;\n local: Vector3;\n}\n\n@decorators.componentObserver({\n Event3D: [],\n})\nexport default class Event3DSystem extends Renderer3D {\n static systemName = 'Event3DSystem';\n name: string = 'Event3DSystem';\n\n private raycaster = new Raycaster();\n private ndc = new Vector2();\n private localScratch = new Vector3();\n private downByPointer = new Map<number, PointerHit>();\n private canvas: HTMLCanvasElement | null = null;\n\n private onPointerDown = (e: PointerEvent) => this.handlePointer(e, 'touchstart');\n private onPointerMove = (e: PointerEvent) => this.handlePointer(e, 'touchmove');\n private onPointerUp = (e: PointerEvent) => this.handlePointer(e, 'touchend');\n private onPointerCancel = (e: PointerEvent) => this.handlePointer(e, 'touchcancel');\n\n init(_params?: Event3DSystemParams) {\n const renderer3DSystem = this.game.getSystem(Renderer3DSystem) as Renderer3DSystem;\n renderer3DSystem.rendererManager.register(this);\n\n this.canvas = this.threeContext.renderer.domElement;\n this.canvas.style.touchAction = 'none';\n this.canvas.addEventListener('pointerdown', this.onPointerDown);\n this.canvas.addEventListener('pointermove', this.onPointerMove);\n this.canvas.addEventListener('pointerup', this.onPointerUp);\n this.canvas.addEventListener('pointercancel', this.onPointerCancel);\n this.canvas.addEventListener('pointerleave', this.onPointerCancel);\n }\n\n componentChanged(changed: ComponentChanged) {\n if (changed.componentName !== 'Event3D') return;\n if (changed.type === OBSERVER_TYPE.REMOVE) {\n changed.component.removeAllListeners();\n for (const [pointerId, hit] of this.downByPointer) {\n if (hit.gameObject.id === changed.gameObject.id) {\n this.downByPointer.delete(pointerId);\n }\n }\n }\n }\n\n rendererUpdate(_gameObject: GameObject) {}\n\n onDestroy() {\n if (!this.canvas) return;\n this.canvas.removeEventListener('pointerdown', this.onPointerDown);\n this.canvas.removeEventListener('pointermove', this.onPointerMove);\n this.canvas.removeEventListener('pointerup', this.onPointerUp);\n this.canvas.removeEventListener('pointercancel', this.onPointerCancel);\n this.canvas.removeEventListener('pointerleave', this.onPointerCancel);\n this.canvas = null;\n this.downByPointer.clear();\n }\n\n private handlePointer(e: PointerEvent, kind: 'touchstart' | 'touchmove' | 'touchend' | 'touchcancel') {\n const hit = this.hitFromEvent(e);\n const canvasPos = this.canvasPosition(e);\n\n if (kind === 'touchstart') {\n if (!hit) return;\n this.downByPointer.set(e.pointerId, hit);\n this.emitOn(hit, 'touchstart', e, canvasPos);\n return;\n }\n\n if (kind === 'touchmove') {\n if (!hit) return;\n this.emitOn(hit, 'touchmove', e, canvasPos);\n return;\n }\n\n const down = this.downByPointer.get(e.pointerId);\n this.downByPointer.delete(e.pointerId);\n\n if (kind === 'touchcancel') {\n if (down) this.emitOn(down, 'touchcancel', e, canvasPos);\n return;\n }\n\n if (hit && down && hit.gameObject.id === down.gameObject.id) {\n this.emitOn(hit, 'touchend', e, canvasPos);\n this.emitOn(hit, 'tap', e, canvasPos);\n return;\n }\n\n if (down) {\n this.emitOn(down, 'touchendoutside', e, canvasPos);\n }\n if (hit) {\n this.emitOn(hit, 'touchend', e, canvasPos);\n }\n }\n\n private emitOn(\n hit: PointerHit,\n eventName: 'touchstart' | 'touchmove' | 'touchend' | 'tap' | 'touchendoutside' | 'touchcancel',\n e: PointerEvent,\n canvasPos: { x: number; y: number },\n ) {\n let stopped = false;\n hit.component.emit(eventName, {\n stopPropagation: () => { stopped = true; },\n data: {\n pointerId: e.pointerId,\n position: canvasPos,\n localPosition: {\n x: hit.local.x,\n y: hit.local.y,\n z: hit.local.z,\n },\n },\n gameObject: hit.gameObject,\n });\n if (stopped) {\n e.stopPropagation();\n }\n }\n\n private canvasPosition(e: PointerEvent) {\n const rect = this.canvas.getBoundingClientRect();\n return {\n x: e.clientX - rect.left,\n y: e.clientY - rect.top,\n };\n }\n\n private hitFromEvent(e: PointerEvent): PointerHit | null {\n if (!this.canvas) return null;\n const rect = this.canvas.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) return null;\n\n this.ndc.set(\n ((e.clientX - rect.left) / rect.width) * 2 - 1,\n -((e.clientY - rect.top) / rect.height) * 2 + 1,\n );\n this.raycaster.setFromCamera(this.ndc, this.threeContext.camera);\n const intersections = this.raycaster.intersectObjects(this.threeContext.scene.children, true);\n\n for (const intersection of intersections) {\n const id = gameObjectIdFromObject3D(intersection.object);\n if (id == null) continue;\n const gameObject = this.game.gameObjects.find((go) => go.id === id);\n if (!gameObject) continue;\n const component = gameObject.getComponent(Event3D) as Event3D | undefined;\n if (!component) continue;\n\n this.localScratch.copy(intersection.point);\n intersection.object.worldToLocal(this.localScratch);\n return {\n gameObject,\n component,\n local: this.localScratch.clone(),\n };\n }\n return null;\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"plugin-renderer-3d-event.esm.js","sources":["../lib/component.ts","../lib/system.ts"],"sourcesContent":["import { Component } from '@combos-fun/engine';\nimport type { GameObject } from '@combos-fun/engine';\n\ntype TouchEventName = 'touchstart' | 'touchmove' | 'touchend' | 'tap' | 'touchendoutside' | 'touchcancel';\n\nexport type Event3DHitAreaType = 'box' | 'sphere' | 'plane';\n\nexport interface Event3DHitArea {\n type: Event3DHitAreaType | string;\n width?: number;\n height?: number;\n depth?: number;\n radius?: number;\n}\n\nexport type Event3DParam = {\n stopPropagation: () => void,\n data: {\n pointerId: number,\n position: {\n x: number,\n y: number,\n },\n localPosition: {\n x: number,\n y: number,\n z: number,\n },\n },\n gameObject: GameObject,\n};\n\nexport interface Event3DParams {\n hitArea?: Event3DHitArea;\n}\n\nexport default class Event3D extends Component<Event3DParams> {\n static componentName = 'Event3D';\n\n hitArea?: Event3DHitArea;\n\n init(params?: Event3DParams) {\n params && Object.assign(this, params);\n }\n\n emit(eventName: TouchEventName, ...args: [Event3DParam]): boolean\n emit<T extends string>(eventName: Exclude<T, TouchEventName>, ...args: any[]): boolean\n emit(en: string, ...args: any[]) {\n return super.emit(en, ...args);\n }\n\n once(eventName: TouchEventName, fn: (arg: Event3DParam) => void, context?: any): this\n once<T extends string>(eventName: Exclude<T, TouchEventName>, fn: (...args: any[]) => void, context?: any): this\n once(en: string, fn: (...args: any[]) => void, context?: any) {\n return super.once(en, fn, context);\n }\n\n on(eventName: TouchEventName, fn: (arg: Event3DParam) => void, context?: any): this\n on<T extends string>(eventName: Exclude<T, TouchEventName>, fn: (...args: any[]) => void, context?: any): this\n on(en: string, fn: (...args: any[]) => void, context?: any) {\n return super.on(en, fn, context);\n }\n}\n","import { decorators, ComponentChanged, OBSERVER_TYPE, GameObject } from '@combos-fun/engine';\nimport {\n Renderer3D,\n Renderer3DSystem,\n gameObjectIdFromIntersection,\n tagObject3D,\n} from '@combos-fun/plugin-renderer-3d';\nimport {\n BoxGeometry,\n Mesh,\n MeshBasicMaterial,\n PlaneGeometry,\n Raycaster,\n SphereGeometry,\n Vector2,\n Vector3,\n} from 'three';\nimport Event3D from './component';\nimport type { Event3DHitArea } from './component';\n\nexport interface Event3DSystemParams {}\n\ninterface PointerHit {\n gameObject: GameObject;\n component: Event3D;\n local: Vector3;\n}\n\n@decorators.componentObserver({\n Event3D: [{ prop: ['hitArea'], deep: true }],\n})\nexport default class Event3DSystem extends Renderer3D {\n static systemName = 'Event3DSystem';\n name: string = 'Event3DSystem';\n\n private raycaster = new Raycaster();\n private ndc = new Vector2();\n private localScratch = new Vector3();\n private downByPointer = new Map<number, PointerHit>();\n private hitAreas = new Map<number, Mesh>();\n private canvas: HTMLCanvasElement | null = null;\n\n private onPointerDown = (e: PointerEvent) => this.handlePointer(e, 'touchstart');\n private onPointerMove = (e: PointerEvent) => this.handlePointer(e, 'touchmove');\n private onPointerUp = (e: PointerEvent) => this.handlePointer(e, 'touchend');\n private onPointerCancel = (e: PointerEvent) => this.handlePointer(e, 'touchcancel');\n\n init(_params?: Event3DSystemParams) {\n const renderer3DSystem = this.game.getSystem(Renderer3DSystem) as Renderer3DSystem;\n renderer3DSystem.rendererManager.register(this);\n\n this.canvas = this.threeContext.renderer.domElement;\n this.canvas.style.touchAction = 'none';\n this.canvas.addEventListener('pointerdown', this.onPointerDown);\n this.canvas.addEventListener('pointermove', this.onPointerMove);\n this.canvas.addEventListener('pointerup', this.onPointerUp);\n this.canvas.addEventListener('pointercancel', this.onPointerCancel);\n this.canvas.addEventListener('pointerleave', this.onPointerCancel);\n }\n\n componentChanged(changed: ComponentChanged) {\n if (changed.componentName !== 'Event3D') return;\n const component = changed.component as Event3D;\n if (changed.type === OBSERVER_TYPE.ADD) {\n this.syncHitArea(changed.gameObject, component);\n return;\n }\n if (changed.type === OBSERVER_TYPE.CHANGE) {\n this.syncHitArea(changed.gameObject, component);\n return;\n }\n if (changed.type === OBSERVER_TYPE.REMOVE) {\n this.removeHitArea(changed.gameObject.id);\n changed.component.removeAllListeners();\n for (const [pointerId, hit] of this.downByPointer) {\n if (hit.gameObject.id === changed.gameObject.id) {\n this.downByPointer.delete(pointerId);\n }\n }\n }\n }\n\n private syncHitArea(gameObject: GameObject, component: Event3D) {\n this.removeHitArea(gameObject.id);\n if (!component.hitArea) return;\n const mesh = this.createHitAreaMesh(component.hitArea);\n if (!mesh) return;\n tagObject3D(mesh, gameObject.id);\n mesh.name = '__hitArea';\n this.threeContext.attachVisual(gameObject.id, mesh, gameObject);\n this.hitAreas.set(gameObject.id, mesh);\n }\n\n private createHitAreaMesh(hitArea: Event3DHitArea): Mesh | null {\n const type = String(hitArea.type || 'box').toLowerCase();\n let geometry;\n if (type === 'sphere') {\n geometry = new SphereGeometry(hitArea.radius ?? 0.5, 16, 12);\n } else if (type === 'plane') {\n geometry = new PlaneGeometry(hitArea.width ?? 1, hitArea.height ?? 1);\n } else if (type === 'box') {\n geometry = new BoxGeometry(hitArea.width ?? 1, hitArea.height ?? 1, hitArea.depth ?? 1);\n } else {\n return null;\n }\n const material = new MeshBasicMaterial({\n transparent: true,\n opacity: 0,\n depthWrite: false,\n });\n const mesh = new Mesh(geometry, material);\n mesh.visible = true;\n return mesh;\n }\n\n private removeHitArea(id: number) {\n const mesh = this.hitAreas.get(id);\n if (!mesh) return;\n this.threeContext.detachVisual(id, mesh);\n mesh.geometry.dispose();\n (mesh.material as MeshBasicMaterial).dispose();\n this.hitAreas.delete(id);\n }\n\n rendererUpdate(_gameObject: GameObject) {}\n\n onDestroy() {\n if (!this.canvas) return;\n this.canvas.removeEventListener('pointerdown', this.onPointerDown);\n this.canvas.removeEventListener('pointermove', this.onPointerMove);\n this.canvas.removeEventListener('pointerup', this.onPointerUp);\n this.canvas.removeEventListener('pointercancel', this.onPointerCancel);\n this.canvas.removeEventListener('pointerleave', this.onPointerCancel);\n this.canvas = null;\n this.downByPointer.clear();\n for (const [id] of this.hitAreas) {\n this.removeHitArea(id);\n }\n this.hitAreas.clear();\n }\n\n private handlePointer(e: PointerEvent, kind: 'touchstart' | 'touchmove' | 'touchend' | 'touchcancel') {\n const hit = this.hitFromEvent(e);\n const canvasPos = this.canvasPosition(e);\n\n if (kind === 'touchstart') {\n if (!hit) return;\n this.downByPointer.set(e.pointerId, hit);\n this.emitOn(hit, 'touchstart', e, canvasPos);\n return;\n }\n\n if (kind === 'touchmove') {\n if (!hit) return;\n this.emitOn(hit, 'touchmove', e, canvasPos);\n return;\n }\n\n const down = this.downByPointer.get(e.pointerId);\n this.downByPointer.delete(e.pointerId);\n\n if (kind === 'touchcancel') {\n if (down) this.emitOn(down, 'touchcancel', e, canvasPos);\n return;\n }\n\n if (hit && down && hit.gameObject.id === down.gameObject.id) {\n this.emitOn(hit, 'touchend', e, canvasPos);\n this.emitOn(hit, 'tap', e, canvasPos);\n return;\n }\n\n if (down) {\n this.emitOn(down, 'touchendoutside', e, canvasPos);\n }\n if (hit) {\n this.emitOn(hit, 'touchend', e, canvasPos);\n }\n }\n\n private emitOn(\n hit: PointerHit,\n eventName: 'touchstart' | 'touchmove' | 'touchend' | 'tap' | 'touchendoutside' | 'touchcancel',\n e: PointerEvent,\n canvasPos: { x: number; y: number },\n ) {\n let stopped = false;\n hit.component.emit(eventName, {\n stopPropagation: () => { stopped = true; },\n data: {\n pointerId: e.pointerId,\n position: canvasPos,\n localPosition: {\n x: hit.local.x,\n y: hit.local.y,\n z: hit.local.z,\n },\n },\n gameObject: hit.gameObject,\n });\n if (stopped) {\n e.stopPropagation();\n }\n }\n\n private canvasPosition(e: PointerEvent) {\n const rect = this.canvas.getBoundingClientRect();\n return {\n x: e.clientX - rect.left,\n y: e.clientY - rect.top,\n };\n }\n\n private hitFromEvent(e: PointerEvent): PointerHit | null {\n if (!this.canvas) return null;\n const rect = this.canvas.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) return null;\n\n this.ndc.set(\n ((e.clientX - rect.left) / rect.width) * 2 - 1,\n -((e.clientY - rect.top) / rect.height) * 2 + 1,\n );\n this.raycaster.setFromCamera(this.ndc, this.threeContext.camera);\n const intersections = this.raycaster.intersectObjects(this.threeContext.scene.children, true);\n\n for (const intersection of intersections) {\n const id = gameObjectIdFromIntersection(intersection);\n if (id == null) continue;\n const gameObject = this.game.gameObjects.find((go) => go.id === id);\n if (!gameObject) continue;\n const component = gameObject.getComponent(Event3D) as Event3D | undefined;\n if (!component) continue;\n\n this.localScratch.copy(intersection.point);\n intersection.object.worldToLocal(this.localScratch);\n return {\n gameObject,\n component,\n local: this.localScratch.clone(),\n };\n }\n return null;\n }\n}\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@combos-fun/plugin-renderer-3d-event",
3
- "version": "0.0.42",
3
+ "version": "0.0.45",
4
4
  "description": "Pointer / touch event input via Three.js raycasting",
5
5
  "main": "index.js",
6
6
  "module": "dist/plugin-renderer-3d-event.esm.js",
@@ -27,8 +27,8 @@
27
27
  },
28
28
  "dependencies": {
29
29
  "three": "^0.172.0",
30
- "@combos-fun/engine": "0.0.42",
31
- "@combos-fun/plugin-renderer-3d": "0.0.42"
30
+ "@combos-fun/engine": "0.0.45",
31
+ "@combos-fun/plugin-renderer-3d": "0.0.45"
32
32
  },
33
33
  "keywords": [
34
34
  "combos-fun",