From eefe202d8d0d05a60d66e570170eabe396f17894 Mon Sep 17 00:00:00 2001 From: Erik Onarheim Date: Wed, 10 Jan 2024 20:48:43 -0600 Subject: [PATCH] feat: New graphics events (#2877) This PR adds new graphics events and hooks that allow you to hook into graphics drawing before or after any drawing transformations have been applied * `Actor.graphics.onPreTransformDraw` with the corresponding event `.on('pretransformdraw')` * `Actor.graphics.onPostTransformDraw` with the corresponding event `.on('posttransformdraw')` This is useful if you want to make changes to the transform or totally influence the draw transform DURING the draw step --- CHANGELOG.md | 3 +++ src/engine/Actor.ts | 4 ++++ src/engine/Events.ts | 23 +++++++++++++++++++++++ src/engine/Graphics/GraphicsComponent.ts | 12 +++++++++++- src/engine/Graphics/GraphicsSystem.ts | 15 ++++++++++++++- 5 files changed, 55 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c1004e03..1f82d13b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,9 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Added +- New graphics events and hooks that allow you to hook into graphics drawing before or after any drawing transformations have been applied + * `Actor.graphics.onPreTransformDraw` with the corresponding event `.on('pretransformdraw')` + * `Actor.graphics.onPostTransformDraw` with the corresponding event `.on('posttransformdraw')` - New property and methods overloads to `ex.Animation` * `ex.Animation.currentFrameTimeLeft` will return the current time in milliseconds left in the current * `ex.Animation.goToFrame(frameNumber: number, duration?: number)` now accepts an optional duration for the target frame diff --git a/src/engine/Actor.ts b/src/engine/Actor.ts index 55ec6b3ec..27bda1d6a 100644 --- a/src/engine/Actor.ts +++ b/src/engine/Actor.ts @@ -152,6 +152,8 @@ export type ActorEvents = EntityEvents & { postkill: PostKillEvent; predraw: PreDrawEvent; postdraw: PostDrawEvent; + pretransformdraw: PreDrawEvent; + posttransformdraw: PostDrawEvent; predebugdraw: PreDebugDrawEvent; postdebugdraw: PostDebugDrawEvent; pointerup: PointerEvent; @@ -182,6 +184,8 @@ export const ActorEvents = { PostKill: 'postkill', PreDraw: 'predraw', PostDraw: 'postdraw', + PreTransformDraw: 'pretransformdraw', + PostTransformDraw: 'posttransformdraw', PreDebugDraw: 'predebugdraw', PostDebugDraw: 'postdebugdraw', PointerUp: 'pointerup', diff --git a/src/engine/Events.ts b/src/engine/Events.ts index 43d5bf50c..f25615789 100644 --- a/src/engine/Events.ts +++ b/src/engine/Events.ts @@ -263,6 +263,29 @@ export class PostDrawEvent extends GameEvent } } +/** + * The 'pretransformdraw' event is emitted on actors/entities before any graphics transforms have taken place. + * Useful if you need to completely customize the draw or modify the transform before drawing in the draw step (for example needing + * latest camera positions) + * + */ +export class PreTransformDrawEvent extends GameEvent { + constructor(public ctx: ExcaliburGraphicsContext, public delta: number, public target: Entity) { + super(); + } +} + +/** + * The 'posttransformdraw' event is emitted on actors/entities after all graphics have been draw and transforms reset. + * Useful if you need to completely custom the draw after everything is done. + * + */ +export class PostTransformDrawEvent extends GameEvent { + constructor(public ctx: ExcaliburGraphicsContext, public delta: number, public target: Entity) { + super(); + } +} + /** * The 'predebugdraw' event is emitted on actors, scenes, and engine before debug drawing starts. */ diff --git a/src/engine/Graphics/GraphicsComponent.ts b/src/engine/Graphics/GraphicsComponent.ts index c9b27a216..137422bbd 100644 --- a/src/engine/Graphics/GraphicsComponent.ts +++ b/src/engine/Graphics/GraphicsComponent.ts @@ -278,7 +278,7 @@ export class GraphicsComponent extends Component<'ex.graphics'> { } /** - * Draws after the entity transform has bene applied, but before graphics component graphics have been drawn + * Draws after the entity transform has been applied, but before graphics component graphics have been drawn */ public onPreDraw: (ctx: ExcaliburGraphicsContext, elapsedMilliseconds: number) => void; @@ -287,6 +287,16 @@ export class GraphicsComponent extends Component<'ex.graphics'> { */ public onPostDraw: (ctx: ExcaliburGraphicsContext, elapsedMilliseconds: number) => void; + /** + * Draws before the entity transform has been applied before any any graphics component drawing + */ + public onPreTransformDraw: (ctx: ExcaliburGraphicsContext, elapsedMilliseconds: number) => void; + + /** + * Draws after the entity transform has been applied, and after all graphics component drawing + */ + public onPostTransformDraw: (ctx: ExcaliburGraphicsContext, elapsedMilliseconds: number) => void; + /** * Sets or gets wether any drawing should be visible in this component */ diff --git a/src/engine/Graphics/GraphicsSystem.ts b/src/engine/Graphics/GraphicsSystem.ts index 187dce74e..a6c48eb00 100644 --- a/src/engine/Graphics/GraphicsSystem.ts +++ b/src/engine/Graphics/GraphicsSystem.ts @@ -13,7 +13,8 @@ import { ParallaxComponent } from './ParallaxComponent'; import { CoordPlane } from '../Math/coord-plane'; import { BodyComponent } from '../Collision/BodyComponent'; import { FontCache } from './FontCache'; -import { PostDrawEvent, PreDrawEvent, Transform } from '..'; +import { PostDrawEvent, PostTransformDrawEvent, PreDrawEvent, PreTransformDrawEvent } from '../Events'; +import { Transform } from '../Math/transform'; import { blendTransform } from './TransformInterpolation'; export class GraphicsSystem extends System { @@ -92,6 +93,12 @@ export class GraphicsSystem extends System