From 65e3cccad717cd68e7bed966075625c15ef2a8fb Mon Sep 17 00:00:00 2001 From: Forrest Sun Date: Sun, 28 Jul 2024 08:45:00 -0700 Subject: [PATCH] add event listeners to particle system --- packages/quarks.core/package.json | 2 +- packages/quarks.core/src/IParticleSystem.ts | 8 ++++ packages/quarks.nodes/package.json | 2 +- packages/quarks.nodes/src/nodes/NodeVFX.ts | 38 ++++++++++++++++++- .../three.quarks/examples/explosionDemo.js | 6 +++ packages/three.quarks/package.json | 4 +- packages/three.quarks/src/ParticleSystem.ts | 31 ++++++++++++++- 7 files changed, 85 insertions(+), 6 deletions(-) diff --git a/packages/quarks.core/package.json b/packages/quarks.core/package.json index e2975af..8ea4ef0 100644 --- a/packages/quarks.core/package.json +++ b/packages/quarks.core/package.json @@ -1,6 +1,6 @@ { "name": "quarks.core", - "version": "0.15.2", + "version": "0.15.3", "description": "Core library for Quarks VFX / Particle System Library", "type": "module", "types": "./dist/types/index.d.ts", diff --git a/packages/quarks.core/src/IParticleSystem.ts b/packages/quarks.core/src/IParticleSystem.ts index 761cd37..25a6765 100644 --- a/packages/quarks.core/src/IParticleSystem.ts +++ b/packages/quarks.core/src/IParticleSystem.ts @@ -90,6 +90,11 @@ export interface IEmitter { matrixWorld: any; //type is annoying } +export type ParticleSystemEventType = "emitEnd" | "destroy"; +export interface ParticleSystemEvent { + type: ParticleSystemEventType; + particleSystem: IParticleSystem; +} export interface IParticleSystem { @@ -152,4 +157,7 @@ export interface IParticleSystem { emit(delta: number, subEmissionState: EmissionState, matrix: Matrix4): void; + addEventListener(event: ParticleSystemEventType, callback: (event: ParticleSystemEvent)=>void): void; + removeEventListener(event: ParticleSystemEventType, callback: (event: ParticleSystemEvent)=>void): void; + removeAllEventListeners(event: ParticleSystemEventType): void; } diff --git a/packages/quarks.nodes/package.json b/packages/quarks.nodes/package.json index e1a73ef..8f4aa4d 100644 --- a/packages/quarks.nodes/package.json +++ b/packages/quarks.nodes/package.json @@ -4,7 +4,7 @@ "description": "node based behavior and render system for quarks engine", "type": "module", "dependencies": { - "three.quarks": "^0.15.2" + "three.quarks": "^0.15.3" }, "devDependencies": { "@types/three": "^0.165.0", diff --git a/packages/quarks.nodes/src/nodes/NodeVFX.ts b/packages/quarks.nodes/src/nodes/NodeVFX.ts index 608ceab..bd4f78b 100644 --- a/packages/quarks.nodes/src/nodes/NodeVFX.ts +++ b/packages/quarks.nodes/src/nodes/NodeVFX.ts @@ -15,7 +15,14 @@ import { EmissionState, IEmitter, } from 'quarks.core'; -import {ParticleEmitter, RenderMode, BatchedRenderer, VFXBatchSettings} from 'three.quarks'; +import { + ParticleEmitter, + RenderMode, + BatchedRenderer, + VFXBatchSettings, + ParticleSystemEventType, + ParticleSystemEvent, +} from 'three.quarks'; import { BufferGeometry, Layers, @@ -353,6 +360,7 @@ export class NodeVFX implements IParticleSystem { if (this.autoDestroy) { this.markForDestroy = true; } + this.fire({type: "emitEnd", particleSystem: this}); } dispose() { @@ -361,6 +369,7 @@ export class NodeVFX implements IParticleSystem { emitter.dispose(); if (emitter.parent) emitter.parent!.remove(emitter); + this.fire({type: "destroy", particleSystem: this}); } restart() { @@ -499,4 +508,31 @@ export class NodeVFX implements IParticleSystem { } speedFactor = 0; + + private listeners: {[event: string]: Array<(event: ParticleSystemEvent)=>void>} = {}; + addEventListener(event: ParticleSystemEventType, callback: (event: ParticleSystemEvent) => void): void { + if (!this.listeners[event]) + this.listeners[event] = []; + this.listeners[event].push(callback); + } + + removeAllEventListeners(event: ParticleSystemEventType): void { + if (this.listeners[event]) + this.listeners[event] = []; + } + + removeEventListener(event: ParticleSystemEventType, callback: (event: ParticleSystemEvent) => void): void { + if (this.listeners[event]) { + const index = this.listeners[event].indexOf(callback); + if (index !== -1) { + this.listeners[event].splice(index, 1); + } + } + } + + private fire(event: ParticleSystemEvent) { + if (this.listeners[event.type]) { + this.listeners[event.type].forEach(callback => callback(event)); + } + } } diff --git a/packages/three.quarks/examples/explosionDemo.js b/packages/three.quarks/examples/explosionDemo.js index e9a16b1..7faa7f8 100644 --- a/packages/three.quarks/examples/explosionDemo.js +++ b/packages/three.quarks/examples/explosionDemo.js @@ -13,9 +13,15 @@ export class ExplosionDemo extends Demo { this.batchRenderer = new BatchedParticleRenderer(); this.scene.add(this.batchRenderer); + function listener(event) { + console.log(event.type); + } new QuarksLoader().load('ps.json', (obj) => { QuarksUtil.addToBatchRenderer(obj, this.batchRenderer); + QuarksUtil.runOnAllParticleEmitters(obj, (emitter) => { + emitter.system.addEventListener("emitEnd", listener); + }) this.scene.add(obj); this.groups.push(obj); }); diff --git a/packages/three.quarks/package.json b/packages/three.quarks/package.json index f9011a8..af9e30d 100644 --- a/packages/three.quarks/package.json +++ b/packages/three.quarks/package.json @@ -1,6 +1,6 @@ { "name": "three.quarks", - "version": "0.15.2", + "version": "0.15.3", "description": "A General-Purpose Particle System for three.js", "type": "module", "types": "./dist/types/index.d.ts", @@ -60,7 +60,7 @@ "three": ">=0.165.0" }, "dependencies": { - "quarks.core": "^0.15.2" + "quarks.core": "^0.15.3" }, "devDependencies": { "@types/jest": "^29.5.12", diff --git a/packages/three.quarks/src/ParticleSystem.ts b/packages/three.quarks/src/ParticleSystem.ts index ce3b6c2..d04309a 100644 --- a/packages/three.quarks/src/ParticleSystem.ts +++ b/packages/three.quarks/src/ParticleSystem.ts @@ -30,7 +30,7 @@ import { Matrix3, Matrix4, Quaternion, - Vector3Generator, + Vector3Generator, ParticleSystemEvent, ParticleSystemEventType, } from 'quarks.core'; import {MetaData, ParticleEmitter} from './ParticleEmitter'; import { @@ -455,6 +455,7 @@ export class ParticleSystem implements IParticleSystem { private normalMatrix: Matrix3 = new Matrix3(); private memory: GeneratorMemory = []; + private listeners: {[event: string]: Array<(event: ParticleSystemEvent)=>void>} = {}; /** @internal **/ _renderer?: BatchedRenderer; @@ -920,6 +921,7 @@ export class ParticleSystem implements IParticleSystem { if (this.autoDestroy) { this.markForDestroy = true; } + this.fire({type: "emitEnd", particleSystem: this}); } /** @@ -929,6 +931,7 @@ export class ParticleSystem implements IParticleSystem { if (this._renderer) this._renderer.deleteSystem(this); this.emitter.dispose(); if (this.emitter.parent) this.emitter.parent.remove(this.emitter); + this.fire({type: "destroy", particleSystem: this}); } /** @@ -1353,6 +1356,32 @@ export class ParticleSystem implements IParticleSystem { return this.rendererSettings; } + addEventListener(event: ParticleSystemEventType, callback: (event: ParticleSystemEvent) => void): void { + if (!this.listeners[event]) + this.listeners[event] = []; + this.listeners[event].push(callback); + } + + removeAllEventListeners(event: ParticleSystemEventType): void { + if (this.listeners[event]) + this.listeners[event] = []; + } + + removeEventListener(event: ParticleSystemEventType, callback: (event: ParticleSystemEvent) => void): void { + if (this.listeners[event]) { + const index = this.listeners[event].indexOf(callback); + if (index !== -1) { + this.listeners[event].splice(index, 1); + } + } + } + + private fire(event: ParticleSystemEvent) { + if (this.listeners[event.type]) { + this.listeners[event.type].forEach(callback => callback(event)); + } + } + /** * Clone the particle system */