Skip to content

Commit

Permalink
fix: Issue with pointer events on screen elements (#2902)
Browse files Browse the repository at this point in the history
This PR fixes an issue discovered on the discord around pointer events and ScreenElements

- Fixed issue where pointer events did not work properly when using [[ScreenElement]]s
- Fixed issue where debug draw was not accurate when using *AndFill suffixed [[DisplayMode]]s
  • Loading branch information
eonarheim committed Jan 26, 2024
1 parent 08ce7e3 commit df71c3b
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 9 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).

### Fixed

-
- Fixed issue where pointer events did not work properly when using [[ScreenElement]]s
- Fixed issue where debug draw was not accurate when using *AndFill suffixed [[DisplayMode]]s

### Updates

Expand Down
28 changes: 27 additions & 1 deletion sandbox/tests/pointer/pointer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,24 @@ class Player extends ex.Actor {

class Game2 extends ex.Engine {
initialize() {
const screenElement = new ex.ScreenElement({
x: 100,
y: 100,
height: 50,
width: 100,
color: ex.Color.Red
});
screenElement.pointer.useColliderShape = true;
screenElement.pointer.useGraphicsBounds = true;
screenElement.on('pointerdown', () => {
console.log('screen element down')
});
screenElement.on('pointerup', () => {
console.log('screen element up')
});
this.add(screenElement);


const player1 = new Player(ex.Color.Green);
this.add(player1);
player1.z = 10;
Expand Down Expand Up @@ -44,6 +62,14 @@ class Game2 extends ex.Engine {
this.start(loader);
}
}
var game2 = new Game2({width: 600, height: 400});
var game2 = new Game2({
width: 600,
height: 400,
antialiasing: false,
displayMode: ex.DisplayMode.FitScreenAndFill
});
game2.debug.collider.showBounds = true;
game2.debug.graphics.showBounds = true;
game2.toggleDebug();

game2.initialize();
2 changes: 1 addition & 1 deletion src/engine/Camera.ts
Original file line number Diff line number Diff line change
Expand Up @@ -691,7 +691,7 @@ export class Camera implements CanUpdate, CanInitialize {
}

public updateViewport() {
// recalc viewport
// recalculate viewport
this._viewport = new BoundingBox(
this.x - this._halfWidth,
this.y - this._halfHeight,
Expand Down
6 changes: 6 additions & 0 deletions src/engine/Debug/DebugSystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ export class DebugSystem extends System<TransformComponent> {
this._pushCameraTransform(tx);

this._graphicsContext.save();
if (tx.coordPlane === CoordPlane.Screen) {
this._graphicsContext.translate(this._engine.screen.contentArea.left, this._engine.screen.contentArea.top);
}
this._graphicsContext.z = txSettings.debugZIndex;

this._applyTransform(entity);
Expand Down Expand Up @@ -185,6 +188,9 @@ export class DebugSystem extends System<TransformComponent> {

// World space
this._graphicsContext.save();
if (tx.coordPlane === CoordPlane.Screen) {
this._graphicsContext.translate(this._engine.screen.contentArea.left, this._engine.screen.contentArea.top);
}
this._graphicsContext.z = txSettings.debugZIndex;
motion = entity.get(MotionComponent);
if (motion) {
Expand Down
27 changes: 25 additions & 2 deletions src/engine/Graphics/GraphicsComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { Logger } from '../Util/Log';
import { BoundingBox } from '../Collision/Index';
import { Component } from '../EntityComponentSystem/Component';
import { Material } from './Context/material';
import { Logger } from '../Util/Log';
import { WatchVector } from '../Math/watch-vector';

/**
* Type guard for checking if a Graphic HasTick (used for graphics that change over time like animations)
Expand Down Expand Up @@ -307,15 +309,36 @@ export class GraphicsComponent extends Component<'ex.graphics'> {
*/
public opacity: number = 1;


private _offset: Vector = Vector.Zero;

/**
* Offset to apply to graphics by default
*/
public offset: Vector = Vector.Zero;
public get offset(): Vector {
return new WatchVector(this._offset, () => {
this.recalculateBounds();
});
}
public set offset(value: Vector) {
this._offset = value;
this.recalculateBounds();
}

private _anchor: Vector = Vector.Half;

/**
* Anchor to apply to graphics by default
*/
public anchor: Vector = Vector.Half;
public get anchor(): Vector {
return new WatchVector(this._anchor, () => {
this.recalculateBounds();
});
}
public set anchor(value: Vector) {
this._anchor = value;
this.recalculateBounds();
}

/**
* Flip all graphics horizontally along the y-axis
Expand Down
11 changes: 10 additions & 1 deletion src/engine/Screen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,8 @@ export class Screen {
* Excalibur screen space.
*
* Excalibur screen space starts at the top left (0, 0) corner of the viewport, and extends to the
* bottom right corner (resolutionX, resolutionY)
* bottom right corner (resolutionX, resolutionY). When using *AndFill suffixed display modes screen space
* (0, 0) is the top left of the safe content area bounding box not the viewport.
* @param point
*/
public pageToScreenCoordinates(point: Vector): Vector {
Expand Down Expand Up @@ -575,6 +576,10 @@ export class Screen {
newX = (newX / this.viewport.width) * this.resolution.width;
newY = (newY / this.viewport.height) * this.resolution.height;

// offset by content area
newX = newX - this.contentArea.left;
newY = newY - this.contentArea.top;

return new Vector(newX, newY);
}

Expand All @@ -590,6 +595,10 @@ export class Screen {
let newX = point.x;
let newY = point.y;

// offset by content area
newX = newX + this.contentArea.left;
newY = newY + this.contentArea.top;

newX = (newX / this.resolution.width) * this.viewport.width;
newY = (newY / this.resolution.height) * this.viewport.height;

Expand Down
6 changes: 3 additions & 3 deletions src/spec/ActorSpec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,11 +146,11 @@ describe('A game actor', () => {
it('should have constructor anchor set on graphics component', () => {
const actor = new ex.Actor({anchor: ex.vec(.7, .7)});

expect(actor.anchor).toEqual(ex.vec(.7, .7));
expect(actor.graphics.anchor).toEqual(ex.vec(.7, .7));
expect(actor.anchor).toBeVector(ex.vec(.7, .7));
expect(actor.graphics.anchor).toBeVector(ex.vec(.7, .7));

actor.anchor = ex.vec(0, 0);
expect(actor.graphics.anchor).toEqual(ex.vec(0, 0));
expect(actor.graphics.anchor).toBeVector(ex.vec(0, 0));
});

it('will inherit the scene from the parent entity after being added', () => {
Expand Down
36 changes: 36 additions & 0 deletions src/spec/PointerInputSpec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,42 @@ describe('A pointer', () => {
expect(actualOrder).toEqual(['actor4', 'actor3', 'actor2', 'actor1']);
});

it('should dispatch point events on screen elements', () => {
const pointerDownSpy = jasmine.createSpy('pointerdown');
const screenElement = new ex.ScreenElement({
x: 50,
y: 50,
width: 100,
height: 100,
color: ex.Color.Red
});
screenElement.on('pointerdown', pointerDownSpy);

engine.add(screenElement);

executeMouseEvent('pointerdown', <any>document, null, 50, 50);
executeMouseEvent('pointerdown', <any>document, null, 50, 150);
executeMouseEvent('pointerdown', <any>document, null, 150, 50);
executeMouseEvent('pointerdown', <any>document, null, 150, 150);
executeMouseEvent('pointerdown', <any>document, null, 100, 100);

engine.currentScene.update(engine, 0);

expect(pointerDownSpy).toHaveBeenCalledTimes(5);

pointerDownSpy.calls.reset();

executeMouseEvent('pointerdown', <any>document, null, 49, 49);
executeMouseEvent('pointerdown', <any>document, null, 49, 151);
executeMouseEvent('pointerdown', <any>document, null, 151, 49);
executeMouseEvent('pointerdown', <any>document, null, 151, 151);

engine.currentScene.update(engine, 0);

expect(pointerDownSpy).toHaveBeenCalledTimes(0);

});

it('can have pointer event canceled', () => {
const actualOrder = [];

Expand Down

0 comments on commit df71c3b

Please sign in to comment.