diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a639f82..788d31f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -74,6 +74,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Fixed +- Fixed issue where pointer containment WAS NOT being uses on collision shape geometry, only their bounds - Fixed issue where overriding built in uniforms and graphics no longer worked as v0.30.x - Fixed issue where clearSchedule during a scheduled callback could cause a cb to be skipped - Fixed issue where specifying custom events was difficult in TypeScript switched from `export type ...Events {` to `export interface ...Events {` which allows declaration merging by user game code to specify custom events diff --git a/src/engine/Input/PointerSystem.ts b/src/engine/Input/PointerSystem.ts index 7d39627c..c02ce929 100644 --- a/src/engine/Input/PointerSystem.ts +++ b/src/engine/Input/PointerSystem.ts @@ -136,7 +136,9 @@ export class PointerSystem extends System { const collider = colliders[i]; const maybePointer = this._entityToPointer.get(collider.owner); if (maybePointer && (maybePointer.useColliderShape || this.overrideUseColliderShape)) { - this._pointerEventDispatcher.addPointerToObject(collider.owner, pointerId); + if (collider.contains(pos.worldPos)) { + this._pointerEventDispatcher.addPointerToObject(collider.owner, pointerId); + } } } diff --git a/src/spec/vitest/PointerInputSpec.ts b/src/spec/vitest/PointerInputSpec.ts index 40f87767..eb95b4ec 100644 --- a/src/spec/vitest/PointerInputSpec.ts +++ b/src/spec/vitest/PointerInputSpec.ts @@ -170,6 +170,38 @@ describe('A pointer', () => { expect(actualOrder).toEqual(['actor4', 'actor3', 'actor2', 'actor1']); }); + it('should dispatch events on colliders correctly using geometry containment', () => { + const pointerSpy = vi.fn(); + + const actor1 = new ex.Actor({ x: 50, y: 50, radius: 50 }); + actor1.z = 0; + actor1.on('pointerdown', (e) => { + pointerSpy(e.worldPos); + }); + + engine.add(actor1); + + executeMouseEvent('pointerdown', document, null, 100, 100); + engine.currentScene.update(engine, 0); + expect(pointerSpy).not.toHaveBeenCalled(); + + executeMouseEvent('pointerdown', document, null, 0, 0); + engine.currentScene.update(engine, 0); + expect(pointerSpy).not.toHaveBeenCalled(); + + executeMouseEvent('pointerdown', document, null, 50, 50); + engine.currentScene.update(engine, 0); + expect(pointerSpy).toHaveBeenCalledWith(ex.vec(50, 50)); + + executeMouseEvent('pointerdown', document, null, Math.cos(0) * 50, 0); + engine.currentScene.update(engine, 0); + expect(pointerSpy).toHaveBeenCalledWith(ex.vec(Math.cos(0) * 50, 0)); + + executeMouseEvent('pointerdown', document, null, Math.cos(0) * 50.1, 0); + engine.currentScene.update(engine, 0); + expect(pointerSpy).not.toHaveBeenCalledWith(ex.vec(Math.cos(0) * 50.1, 0)); + }); + it('should not dispatch canceled events to the top level', () => { const actor1 = new ex.Actor({ x: 50, y: 50, width: 100, height: 100 });