@needle-tools/engine 2.42.0-pre → 2.44.0-pre

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.
Files changed (62) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/needle-engine.d.ts +224 -81
  3. package/dist/needle-engine.js +3836 -422
  4. package/dist/needle-engine.js.map +4 -4
  5. package/dist/needle-engine.min.js +40 -40
  6. package/dist/needle-engine.min.js.map +4 -4
  7. package/lib/engine/engine_element_loading.js +22 -6
  8. package/lib/engine/engine_element_loading.js.map +1 -1
  9. package/lib/engine/engine_input.js +17 -6
  10. package/lib/engine/engine_input.js.map +1 -1
  11. package/lib/engine/engine_serialization_builtin_serializer.js +60 -58
  12. package/lib/engine/engine_serialization_builtin_serializer.js.map +1 -1
  13. package/lib/engine/engine_three_utils.d.ts +1 -0
  14. package/lib/engine/engine_three_utils.js +10 -0
  15. package/lib/engine/engine_three_utils.js.map +1 -1
  16. package/lib/engine/engine_time.js +2 -0
  17. package/lib/engine/engine_time.js.map +1 -1
  18. package/lib/engine/extensions/NEEDLE_techniques_webgl.js +42 -0
  19. package/lib/engine/extensions/NEEDLE_techniques_webgl.js.map +1 -1
  20. package/lib/engine-components/Animation.d.ts +3 -1
  21. package/lib/engine-components/Animation.js +25 -1
  22. package/lib/engine-components/Animation.js.map +1 -1
  23. package/lib/engine-components/AnimatorController.js +4 -1
  24. package/lib/engine-components/AnimatorController.js.map +1 -1
  25. package/lib/engine-components/Camera.d.ts +3 -0
  26. package/lib/engine-components/Camera.js +17 -9
  27. package/lib/engine-components/Camera.js.map +1 -1
  28. package/lib/engine-components/ParticleSystem.d.ts +33 -7
  29. package/lib/engine-components/ParticleSystem.js +464 -249
  30. package/lib/engine-components/ParticleSystem.js.map +1 -1
  31. package/lib/engine-components/ParticleSystemBehaviours.d.ts +0 -0
  32. package/lib/engine-components/ParticleSystemBehaviours.js +2 -0
  33. package/lib/engine-components/ParticleSystemBehaviours.js.map +1 -0
  34. package/lib/engine-components/ParticleSystemModules.d.ts +123 -20
  35. package/lib/engine-components/ParticleSystemModules.js +461 -63
  36. package/lib/engine-components/ParticleSystemModules.js.map +1 -1
  37. package/lib/engine-components/WebXRController.d.ts +1 -0
  38. package/lib/engine-components/WebXRController.js +2 -1
  39. package/lib/engine-components/WebXRController.js.map +1 -1
  40. package/lib/engine-components/codegen/components.d.ts +6 -0
  41. package/lib/engine-components/codegen/components.js +6 -0
  42. package/lib/engine-components/codegen/components.js.map +1 -1
  43. package/lib/engine-components/js-extensions/RGBAColor.d.ts +1 -0
  44. package/lib/engine-components/js-extensions/RGBAColor.js +7 -0
  45. package/lib/engine-components/js-extensions/RGBAColor.js.map +1 -1
  46. package/package.json +2 -1
  47. package/src/engine/codegen/register_types.js +24 -0
  48. package/src/engine/engine_element_loading.ts +22 -5
  49. package/src/engine/engine_input.ts +16 -7
  50. package/src/engine/engine_serialization_builtin_serializer.ts +59 -57
  51. package/src/engine/engine_three_utils.ts +11 -2
  52. package/src/engine/engine_time.ts +1 -0
  53. package/src/engine/extensions/NEEDLE_techniques_webgl.ts +43 -1
  54. package/src/engine-components/Animation.ts +18 -2
  55. package/src/engine-components/AnimatorController.ts +5 -1
  56. package/src/engine-components/Camera.ts +17 -10
  57. package/src/engine-components/ParticleSystem.ts +526 -303
  58. package/src/engine-components/ParticleSystemBehaviours.ts +0 -0
  59. package/src/engine-components/ParticleSystemModules.ts +408 -66
  60. package/src/engine-components/WebXRController.ts +2 -1
  61. package/src/engine-components/codegen/components.ts +6 -0
  62. package/src/engine-components/js-extensions/RGBAColor.ts +7 -0
@@ -4,23 +4,31 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { Behaviour } from "./Component";
7
+ import { Behaviour, GameObject } from "./Component";
8
8
  import * as THREE from "three";
9
- import { MainModule, EmissionModule, ShapeModule, ColorOverLifetimeModule, SizeOverLifetimeModule, NoiseModule, ParticleSystemSimulationSpace, ParticleBurst, ParticleSystemRenderMode } from "./ParticleSystemModules";
9
+ import { MainModule, EmissionModule, ShapeModule, ColorOverLifetimeModule, SizeOverLifetimeModule, NoiseModule, ParticleSystemSimulationSpace, ParticleBurst, ParticleSystemRenderMode, VelocityOverLifetimeModule, TextureSheetAnimationModule, RotationOverLifetimeModule, LimitVelocityOverLifetimeModule, RotationBySpeedModule } from "./ParticleSystemModules";
10
10
  import { getParam } from "../engine/engine_utils";
11
11
  // https://github.dev/creativelifeform/three-nebula
12
- import System, { Emitter, Position, Life, SpriteRenderer, Particle, Body, MeshRenderer, } from 'three-nebula';
12
+ // import System, { Emitter, Position, Life, SpriteRenderer, Particle, Body, MeshRenderer, } from 'three-nebula';
13
13
  import { serializeable } from "../engine/engine_serialization";
14
- import { Context } from "../engine/engine_setup";
15
- import { AxesHelper, Material, Mesh, Object3D, Vector3 } from "three";
16
- import { getWorldQuaternion, getWorldScale } from "../engine/engine_three_utils";
14
+ import { RGBAColor } from "./js-extensions/RGBAColor";
15
+ import { AxesHelper, Material, Mesh, Object3D, Quaternion, Vector3, Vector4 } from "three";
16
+ import { getWorldPosition, getWorldQuaternion, getWorldScale } from "../engine/engine_three_utils";
17
17
  import { assign } from "../engine/engine_serialization_core";
18
+ import { BatchedParticleRenderer, ConstantColor, ConstantValue, ParticleSystem as _ParticleSystem, RenderMode } from "three.quarks";
19
+ import { createFlatTexture } from "../engine/engine_shaders";
20
+ import { Mathf } from "../engine/engine_math";
18
21
  const debug = getParam("debugparticles");
19
22
  export class ParticleSystemRenderer extends Behaviour {
20
23
  renderMode;
21
24
  particleMaterial;
22
25
  // @serializeable(Mesh)
23
26
  particleMesh;
27
+ get transparent() {
28
+ const res = this.particleMaterial?.transparent ?? false;
29
+ // console.log(res, this.particleMaterial);
30
+ return res;
31
+ }
24
32
  getMesh() {
25
33
  let geo = null;
26
34
  if (this.particleMesh instanceof Mesh) {
@@ -38,18 +46,356 @@ __decorate([
38
46
  __decorate([
39
47
  serializeable(Material)
40
48
  ], ParticleSystemRenderer.prototype, "particleMaterial", void 0);
49
+ class MinMaxCurveFunction {
50
+ _curve;
51
+ constructor(curve) { this._curve = curve; }
52
+ type = "function";
53
+ genValue(t) {
54
+ return this._curve.evaluate(t, Math.random());
55
+ }
56
+ toJSON() {
57
+ throw new Error("Method not implemented.");
58
+ }
59
+ clone() {
60
+ throw new Error("Method not implemented.");
61
+ }
62
+ }
63
+ class MinMaxGradientFunction {
64
+ _curve;
65
+ constructor(curve) { this._curve = curve; }
66
+ type = "function";
67
+ genColor(color, t) {
68
+ const col = this._curve.evaluate(t, Math.random());
69
+ // TODO: incoming color should probably be blended?
70
+ color.set(col.r, col.g, col.b, col.alpha);
71
+ return color;
72
+ }
73
+ toJSON() {
74
+ throw new Error("Method not implemented.");
75
+ }
76
+ clone() {
77
+ throw new Error("Method not implemented.");
78
+ }
79
+ }
80
+ class BaseValueGenerator {
81
+ type = "value";
82
+ toJSON() {
83
+ throw new Error("Method not implemented.");
84
+ }
85
+ clone() {
86
+ throw new Error("Method not implemented.");
87
+ }
88
+ system;
89
+ constructor(system) {
90
+ this.system = system;
91
+ }
92
+ }
93
+ class TextureSheetStartFrameGenerator extends BaseValueGenerator {
94
+ genValue() {
95
+ return this.system.textureSheetAnimation.getStartIndex();
96
+ }
97
+ }
98
+ class ParticleSystemEmissionOverTime extends BaseValueGenerator {
99
+ _lastPosition = new Vector3();
100
+ _lastDistance = 0;
101
+ update() {
102
+ const currentPosition = getWorldPosition(this.system.gameObject);
103
+ this._lastDistance = this._lastPosition.distanceTo(currentPosition);
104
+ this._lastPosition.copy(currentPosition);
105
+ }
106
+ genValue() {
107
+ if (this.system.currentParticles >= this.system.maxParticles)
108
+ return 0;
109
+ // emission over time
110
+ let emission = this.system.emission.rateOverTime.evaluate(this.system.time / this.system.duration, Math.random());
111
+ // if(this.system.currentParticles + emission > this.system.maxParticles)
112
+ // emission = (this.system.maxParticles - this.system.currentParticles);
113
+ // const res = Mathf.clamp(emission, 0, this.system.maxParticles - this.system.currentParticles);
114
+ if (this.system.deltaTime > 0) {
115
+ const distanceEmission = this.system.emission.rateOverDistance.evaluate(this.system.time / this.system.duration, Math.random());
116
+ const meterPerSecond = this._lastDistance / this.system.deltaTime;
117
+ let distanceEmissionValue = meterPerSecond * distanceEmission;
118
+ if (!Number.isFinite(distanceEmissionValue))
119
+ distanceEmissionValue = 0;
120
+ emission += distanceEmissionValue;
121
+ }
122
+ const burst = this.system.emission.getBurst();
123
+ if (burst > 0)
124
+ emission += burst / this.system.deltaTime;
125
+ const maxEmission = (this.system.maxParticles - this.system.currentParticles);
126
+ return Mathf.clamp(emission, 0, maxEmission / this.system.deltaTime);
127
+ }
128
+ }
129
+ class ParticleSystemEmissionOverDistance extends BaseValueGenerator {
130
+ genValue() {
131
+ // this seems not be called yet
132
+ return 0;
133
+ // if (this.system.currentParticles >= this.system.maxParticles) return 0;
134
+ // const emission = this.system.emission.rateOverDistance.evaluate(this.system.time / this.system.duration, Math.random());
135
+ // return emission;
136
+ }
137
+ }
138
+ class ParticleSystemBaseBehaviour {
139
+ system;
140
+ get scaleFactorDiff() {
141
+ return this.system.worldScale.x - this.system.scale;
142
+ }
143
+ constructor(ps) {
144
+ this.system = ps;
145
+ }
146
+ initialize(_particle) {
147
+ }
148
+ update(_particle, _delta) {
149
+ }
150
+ frameUpdate(_delta) {
151
+ }
152
+ toJSON() { throw new Error("Method not implemented."); }
153
+ clone() { throw new Error("Method not implemented."); }
154
+ }
155
+ class TextureSheetAnimationBehaviour extends ParticleSystemBaseBehaviour {
156
+ type = "NeedleTextureSheet";
157
+ update(particle, _delta) {
158
+ const sheet = this.system.textureSheetAnimation;
159
+ if (sheet.enabled) {
160
+ const t01 = particle.age / particle.life;
161
+ const index = sheet.evaluate(t01);
162
+ ;
163
+ if (index !== undefined)
164
+ particle.uvTile = index;
165
+ }
166
+ }
167
+ }
168
+ class RotationBehaviour extends ParticleSystemBaseBehaviour {
169
+ type = "NeedleRotation";
170
+ update(particle, delta) {
171
+ if (particle.rotation === undefined)
172
+ return;
173
+ if (particle.rotation instanceof Quaternion) {
174
+ }
175
+ else {
176
+ if (this.system.rotationOverLifetime.enabled) {
177
+ particle.rotation += this.system.rotationOverLifetime.evaluate(particle.age / particle.life) * delta;
178
+ }
179
+ // HACK flip y
180
+ else
181
+ particle.rotation = Math.PI;
182
+ if (this.system.rotationBySpeed.enabled) {
183
+ const speed = particle.velocity.length();
184
+ particle.rotation += this.system.rotationBySpeed.evaluate(particle.age / particle.life, speed) * delta;
185
+ }
186
+ }
187
+ }
188
+ }
189
+ class SizeBehaviour extends ParticleSystemBaseBehaviour {
190
+ type = "NeedleSize";
191
+ update(particle, _delta) {
192
+ const t = particle.age / particle.life;
193
+ let size = 1;
194
+ if (this.system.sizeOverLifetime.enabled)
195
+ size *= this.system.sizeOverLifetime.evaluate(t).x;
196
+ const scaleFactor = this.system.worldScale.x / this.system.cameraScale;
197
+ particle.size = particle.startSize * size * scaleFactor;
198
+ // console.log(particle.startSize, size, this.system.scale, this.system.cameraScale);
199
+ }
200
+ }
201
+ const $startVelocity = Symbol("startVelocity");
202
+ const $gravityFactor = Symbol("gravityModifier");
203
+ const temp3 = new Vector3();
204
+ const temp4 = new Quaternion();
205
+ class VelocityBehaviour extends ParticleSystemBaseBehaviour {
206
+ type = "NeedleVelocity";
207
+ _gravityDirection = new Vector3();
208
+ initialize(particle) {
209
+ const factor = 1 + this.scaleFactorDiff;
210
+ particle.startSpeed = this.system.main.startSpeed.evaluate(Math.random(), Math.random()) * factor;
211
+ particle.velocity.copy(this.system.shape.getDirection(particle.position)).multiplyScalar(particle.startSpeed);
212
+ if (!particle[$startVelocity])
213
+ particle[$startVelocity] = particle.velocity.clone();
214
+ else
215
+ particle[$startVelocity].copy(particle.velocity);
216
+ const gravityFactor = this.system.main.gravityModifier.evaluate(Math.random(), Math.random()); // * factor;
217
+ particle[$gravityFactor] = gravityFactor;
218
+ this._gravityDirection.set(0, -1, 0);
219
+ if (this.system.main.simulationSpace === ParticleSystemSimulationSpace.Local)
220
+ this._gravityDirection.applyQuaternion(this.system.worldQuaternionInverted);
221
+ }
222
+ update(particle, delta) {
223
+ const baseVelocity = particle[$startVelocity];
224
+ let gravityFactor = particle[$gravityFactor];
225
+ if (gravityFactor !== 0) {
226
+ // gravityFactor *= -1;
227
+ temp3.copy(this._gravityDirection).multiplyScalar(gravityFactor * delta * Math.PI);
228
+ // Gizmos.DrawDirection(particle.position, temp3, 0xff0000, 0, false, 10);
229
+ baseVelocity.add(temp3);
230
+ }
231
+ particle.velocity.copy(baseVelocity);
232
+ const t01 = particle.age / particle.life;
233
+ const noise = this.system.noise;
234
+ if (noise.enabled) {
235
+ noise.apply(0, particle.position, particle.velocity, delta, particle.age, particle.life);
236
+ }
237
+ const velocity = this.system.velocityOverLifetime;
238
+ if (velocity.enabled) {
239
+ velocity.apply(0, particle.position, particle.velocity, delta, particle.age, particle.life);
240
+ }
241
+ const limitVelocityOverLifetime = this.system.limitVelocityOverLifetime;
242
+ if (limitVelocityOverLifetime.enabled) {
243
+ // const factor = this.system.worldScale.x;
244
+ limitVelocityOverLifetime.apply(particle.position, baseVelocity, particle.velocity, particle.size, t01, delta, 1);
245
+ }
246
+ // const speed = particle.velocity.length();
247
+ // particle.velocity.multiplyScalar(1-delta);
248
+ // const vel = this.system.velocityOverLifetime.evaluate(particle.age / particle.life);
249
+ }
250
+ }
251
+ class ColorBehaviour extends ParticleSystemBaseBehaviour {
252
+ type = "NeedleColor";
253
+ initialize(particle) {
254
+ const col = this.system.main.startColor.evaluate(particle.age / particle.life, Math.random());
255
+ particle.startColor.set(col.r, col.g, col.b, col.alpha);
256
+ particle.color.copy(particle.startColor);
257
+ }
258
+ update(particle, _delta) {
259
+ if (this.system.colorOverLifetime.enabled) {
260
+ const t = particle.age / particle.life;
261
+ const col = this.system.colorOverLifetime.color.evaluate(t);
262
+ particle.color.set(col.r, col.g, col.b, col.alpha).multiply(particle.startColor);
263
+ }
264
+ }
265
+ }
266
+ class ParticleSystemInterface {
267
+ system;
268
+ emission;
269
+ get anim() {
270
+ return this.system.textureSheetAnimation;
271
+ }
272
+ constructor(system) {
273
+ this.system = system;
274
+ this.emission = new ParticleSystemEmissionOverTime(this.system);
275
+ }
276
+ update() {
277
+ this.emission.update();
278
+ }
279
+ autoDestroy;
280
+ get looping() { return this.system.main.loop; }
281
+ get duration() { return this.system.duration; }
282
+ get shape() { return this.system.shape; }
283
+ get startLife() { return new MinMaxCurveFunction(this.system.main.startLifetime); }
284
+ get startSpeed() { return new MinMaxCurveFunction(this.system.main.startSpeed); }
285
+ get startRotation() { return new MinMaxCurveFunction(this.system.main.startRotation); }
286
+ get startSize() { return new MinMaxCurveFunction(this.system.main.startSize); }
287
+ startLength; /** start length is for trails */
288
+ get startColor() { return new ConstantColor(new Vector4(1, 1, 1, 1)); }
289
+ get emissionOverTime() { return this.emission; }
290
+ /** this is not supported yet */
291
+ get emissionOverDistance() { return new ParticleSystemEmissionOverDistance(this.system); }
292
+ /** not used - burst is controled via emissionOverTime */
293
+ emissionBursts;
294
+ onlyUsedByOther;
295
+ behaviors = [];
296
+ get instancingGeometry() {
297
+ return this.system.renderer.getMesh().geometry;
298
+ }
299
+ get renderMode() {
300
+ if (this.system.trails["enabled"] === true) {
301
+ return RenderMode.Trail;
302
+ }
303
+ switch (this.system.renderer.renderMode) {
304
+ case ParticleSystemRenderMode.Billboard: return RenderMode.BillBoard;
305
+ // case ParticleSystemRenderMode.Stretch: return RenderMode.Stretch;
306
+ // case ParticleSystemRenderMode.HorizontalBillboard: return RenderMode.HorizontalBillboard;
307
+ // case ParticleSystemRenderMode.VerticalBillboard: return RenderMode.VerticalBillboard;
308
+ case ParticleSystemRenderMode.Mesh: return RenderMode.LocalSpace;
309
+ }
310
+ return RenderMode.BillBoard;
311
+ }
312
+ rendererEmitterSettings = {
313
+ startLength: new ConstantValue(220),
314
+ followLocalOrigin: false,
315
+ };
316
+ get speedFactor() { return this.system.main.simulationSpeed; }
317
+ get texture() {
318
+ const mat = this.system.renderer.particleMaterial;
319
+ if (mat && mat["map"]) {
320
+ const tex = mat["map"];
321
+ tex.premultiplyAlpha = false;
322
+ tex.encoding = THREE.LinearEncoding;
323
+ return tex;
324
+ }
325
+ return createFlatTexture(new RGBAColor(1, 1, 1, 1), 1);
326
+ }
327
+ get startTileIndex() { return new TextureSheetStartFrameGenerator(this.system); }
328
+ get uTileCount() { return this.anim.enabled ? this.anim?.numTilesX : undefined; }
329
+ get vTileCount() { return this.anim.enabled ? this.anim?.numTilesY : undefined; }
330
+ get renderOrder() { return 1; }
331
+ get blending() { return this.system.renderer.particleMaterial?.blending ?? THREE.NormalBlending; }
332
+ get transparent() { return this.system.renderer.transparent; }
333
+ get worldSpace() { return this.system.main.simulationSpace === ParticleSystemSimulationSpace.World; }
334
+ }
335
+ class ParticlesEmissionState {
336
+ burstIndex = 0;
337
+ burstWaveIndex = 0;
338
+ time = 0;
339
+ waitEmiting = 0;
340
+ }
41
341
  export class ParticleSystem extends Behaviour {
342
+ play(includeChildren = false) {
343
+ if (includeChildren) {
344
+ GameObject.foreachComponent(this.gameObject, comp => {
345
+ if (comp instanceof ParticleSystem && comp !== this) {
346
+ comp.play(false);
347
+ }
348
+ }, true);
349
+ }
350
+ this._isPlaying = true;
351
+ this._time = 0;
352
+ // https://github.com/Alchemist0823/three.quarks/pull/35
353
+ if (this._particleSystem) {
354
+ this._particleSystem["emissionState"].time = 0;
355
+ this._particleSystem["emitEnded"] = false;
356
+ }
357
+ this.emission?.reset();
358
+ }
359
+ pause() {
360
+ this._isPlaying = false;
361
+ }
362
+ stop() {
363
+ this._isPlaying = false;
364
+ this._time = 0;
365
+ }
366
+ _state;
367
+ emit(count) {
368
+ if (this._particleSystem) {
369
+ count = Math.min(count, this.maxParticles - this.currentParticles);
370
+ if (!this._state)
371
+ this._state = new ParticlesEmissionState();
372
+ this._state.waitEmiting = count;
373
+ this._state.time = 0;
374
+ const emitEndedState = this._particleSystem["emitEnded"];
375
+ this._particleSystem["emitEnded"] = false;
376
+ this._particleSystem.emit(this.deltaTime, this._state, this._particleSystem.emitter.matrixWorld);
377
+ this._particleSystem["emitEnded"] = emitEndedState;
378
+ }
379
+ }
42
380
  colorOverLifetime;
43
381
  main;
44
382
  emission;
45
383
  sizeOverLifetime;
46
384
  shape;
47
385
  noise;
386
+ // @serializeable(TrailModule)
387
+ trails;
388
+ velocityOverLifetime;
389
+ limitVelocityOverLifetime;
390
+ textureSheetAnimation;
391
+ rotationOverLifetime;
392
+ rotationBySpeed;
48
393
  get renderer() {
49
394
  return this._renderer;
50
395
  }
396
+ get isPlaying() { return this.isPlaying; }
51
397
  get currentParticles() {
52
- return this._system?.getCount() ?? 0;
398
+ return this._particleSystem?.particleNum ?? 0;
53
399
  }
54
400
  get maxParticles() {
55
401
  return this.main.maxParticles;
@@ -60,12 +406,44 @@ export class ParticleSystem extends Behaviour {
60
406
  get duration() {
61
407
  return this.main.duration;
62
408
  }
409
+ get deltaTime() {
410
+ return this.context.time.deltaTime * this.main.simulationSpeed;
411
+ }
412
+ get scale() {
413
+ return this.gameObject.scale.x;
414
+ }
415
+ get cameraScale() {
416
+ return this._cameraScale;
417
+ }
418
+ _cameraScale = 1;
419
+ get container() {
420
+ return this._container;
421
+ }
422
+ get worldspace() {
423
+ return this.main.simulationSpace === ParticleSystemSimulationSpace.World;
424
+ }
425
+ __worldQuaternion = new Quaternion();
426
+ get worldQuaternion() {
427
+ return this.__worldQuaternion;
428
+ }
429
+ _worldQuaternionInverted = new Quaternion();
430
+ get worldQuaternionInverted() {
431
+ return this._worldQuaternionInverted;
432
+ }
433
+ _worldScale = new Vector3();
434
+ get worldScale() {
435
+ return this._worldScale;
436
+ }
63
437
  _renderer;
64
- _system;
65
- _emitter;
66
- _size;
438
+ _batchSystem;
439
+ _particleSystem;
440
+ _interface;
441
+ // private _system!: System;
442
+ // private _emitter: Emitter;
443
+ // private _size!: SizeBehaviour;
67
444
  _container;
68
445
  _time = 0;
446
+ _isPlaying = true;
69
447
  /** called from deserialization */
70
448
  set bursts(arr) {
71
449
  for (let i = 0; i < arr.length; i++) {
@@ -81,125 +459,97 @@ export class ParticleSystem extends Behaviour {
81
459
  _bursts;
82
460
  awake() {
83
461
  this._renderer = this.gameObject.getComponent(ParticleSystemRenderer);
84
- this._system = new System();
462
+ this._container = new Object3D();
463
+ this._container.matrixAutoUpdate = false;
85
464
  if (this.main.simulationSpace == ParticleSystemSimulationSpace.Local) {
86
- this._container = new Object3D();
87
- this._container.matrixAutoUpdate = false;
88
465
  this.gameObject.add(this._container);
89
466
  }
90
- const container = this.main.simulationSpace == ParticleSystemSimulationSpace.Local ? this._container : this.context.scene;
467
+ else {
468
+ this.context.scene.add(this._container);
469
+ }
470
+ // else this._container = this.context.scene;
471
+ this._batchSystem = new BatchedParticleRenderer();
472
+ this._container.add(this._batchSystem);
473
+ this._interface = new ParticleSystemInterface(this);
474
+ this._particleSystem = new _ParticleSystem(this._batchSystem, this._interface);
475
+ this._particleSystem.addBehavior(new SizeBehaviour(this));
476
+ this._particleSystem.addBehavior(new VelocityBehaviour(this));
477
+ this._particleSystem.addBehavior(new ColorBehaviour(this));
478
+ this._particleSystem.addBehavior(new TextureSheetAnimationBehaviour(this));
479
+ this._particleSystem.addBehavior(new RotationBehaviour(this));
480
+ const emitter = this._particleSystem.emitter;
481
+ this.context.scene.add(emitter);
91
482
  if (debug) {
92
483
  console.log(this);
93
484
  this.gameObject.add(new AxesHelper(1));
94
485
  }
95
- const renderMode = this._renderer.renderMode;
96
- let renderer = undefined;
97
- switch (renderMode) {
98
- case ParticleSystemRenderMode.Mesh:
99
- // https://three-nebula-docs.netlify.app/class/src/renderer/meshrenderer.js~meshrenderer
100
- // mesh renderer example: https://github.com/creativelifeform/three-nebula/blob/master/website/components/Examples/MeshRenderer/init.js
101
- renderer = new MeshRenderer(container, THREE);
102
- break;
103
- case ParticleSystemRenderMode.Billboard:
104
- renderer = new SpriteRenderer(container, THREE);
105
- break;
106
- }
107
- if (!renderer) {
108
- console.error("No renderer for particle system");
109
- return;
110
- }
111
- renderer.logRendererType = () => { };
112
- if (renderMode === ParticleSystemRenderMode.Billboard) {
113
- if (this.renderer.particleMaterial) {
114
- const sprite = renderer._body;
115
- sprite.layers.disableAll();
116
- sprite.layers.set(2); // ignore raycasting particles
117
- sprite.renderOrder = 1;
118
- sprite.material.map = this.renderer.particleMaterial.map;
119
- sprite.material.transparent = true;
120
- // sprite.material.sizeAttenuation = false;
121
- sprite.material.blending = this.renderer.particleMaterial.blending;
122
- sprite.material.blendDst = this.renderer.particleMaterial.blendDst;
123
- sprite.material.blendDstAlpha = this.renderer.particleMaterial.blendDstAlpha;
124
- sprite.material.blendEquation = this.renderer.particleMaterial.blendEquation;
125
- sprite.material.blendEquationAlpha = this.renderer.particleMaterial.blendEquationAlpha;
126
- sprite.material.blendSrc = this.renderer.particleMaterial.blendSrc;
127
- sprite.material.blendSrcAlpha = this.renderer.particleMaterial.blendSrcAlpha;
128
- sprite.material.premultipliedAlpha = this.renderer.particleMaterial.premultipliedAlpha;
129
- sprite.material.depthWrite = false;
130
- sprite.material.depthTest = true;
131
- if (debug)
132
- console.log(sprite);
133
- }
134
- }
135
- this._system.addRenderer(renderer);
136
- const initializers = [];
137
- const behaviours = [];
138
- const life = new Life();
139
- life.lifePan = new MinMaxCurveSpan(this.main.startLifetime, 1);
140
- initializers.push(life);
141
- const shape = new Position(this.shape);
142
- initializers.push(shape);
143
- const size = this._size = new SizeBehaviour(this.main.startSize, this.main.startSizeMultiplier);
144
- size.sizeOverLifetimeModule = this.sizeOverLifetime;
145
- behaviours.push(size);
146
- const color = new GradientBehaviour(this.main.startColor, this.colorOverLifetime?.enabled ? this.colorOverLifetime.color : undefined);
147
- behaviours.push(color);
148
- const velocity = new VelocityBehaviour(renderer.container, this.shape, this.noise, this.main.startSpeed, 1);
149
- velocity.gravity = this.main.gravityModifier;
150
- velocity.gravityModifierMultiplier = this.main.gravityModifierMultiplier;
151
- behaviours.push(velocity);
152
- if (renderMode === ParticleSystemRenderMode.Mesh) {
153
- initializers.push(new Body(this._renderer.getMesh()));
154
- }
155
- const emitter = this._emitter = new Emitter({});
156
- emitter.setInitializers(initializers);
157
- emitter.setBehaviours(behaviours);
158
- emitter.setRate(this.emission);
159
- emitter.damping = 0;
486
+ // renderer.logRendererType = () => { };
487
+ // if (renderMode === ParticleSystemRenderMode.Billboard) {
488
+ // if (this.renderer.particleMaterial) {
489
+ // const sprite = renderer._body as Sprite;
490
+ // sprite.layers.disableAll();
491
+ // sprite.layers.set(2); // ignore raycasting particles
492
+ // sprite.renderOrder = 1;
493
+ // sprite.material.map = this.renderer.particleMaterial.map;
494
+ // sprite.material.transparent = true;
495
+ // // sprite.material.sizeAttenuation = false;
496
+ // sprite.material.blending = this.renderer.particleMaterial.blending;
497
+ // sprite.material.blendDst = this.renderer.particleMaterial.blendDst;
498
+ // sprite.material.blendDstAlpha = this.renderer.particleMaterial.blendDstAlpha;
499
+ // sprite.material.blendEquation = this.renderer.particleMaterial.blendEquation;
500
+ // sprite.material.blendEquationAlpha = this.renderer.particleMaterial.blendEquationAlpha;
501
+ // sprite.material.blendSrc = this.renderer.particleMaterial.blendSrc;
502
+ // sprite.material.blendSrcAlpha = this.renderer.particleMaterial.blendSrcAlpha;
503
+ // sprite.material.premultipliedAlpha = this.renderer.particleMaterial.premultipliedAlpha;
504
+ // sprite.material.depthWrite = false;
505
+ // sprite.material.depthTest = true;
506
+ // if (debug) console.log(sprite);
507
+ // }
508
+ // }
509
+ // setInterval(()=>{
510
+ // this.emit(100);
511
+ // }, 1000)
160
512
  }
161
513
  onEnable() {
162
- this._emitter.emit();
163
- this._system.addEmitter(this._emitter);
164
- this._system.emit({ onStart: () => { }, onUpdate: () => { }, onEnd: () => { }, });
165
- this._time = 0;
514
+ this.play();
166
515
  }
167
516
  onDisable() {
168
- this._system.removeEmitter(this._emitter);
169
517
  }
170
518
  onBeforeRender() {
171
519
  if (this._bursts) {
172
520
  this.emission.bursts = this._bursts;
521
+ delete this._bursts;
173
522
  }
523
+ if (!this._isPlaying)
524
+ return;
174
525
  // sprite materials must be scaled in AR
175
526
  const cam = this.context.mainCamera;
176
527
  if (cam) {
177
528
  const scale = getWorldScale(cam);
178
- this._size.cameraScale = scale.x;
529
+ this._cameraScale = scale.x;
179
530
  }
180
- if (this._container && this.gameObject?.parent) {
181
- // this._container.matrix.copy(this.gameObject.matrixWorld);
182
- // this._container.matrixWorld.copy(this.gameObject.matrixWorld);
531
+ let source = this._container;
532
+ if (this.worldspace)
533
+ source = this.gameObject;
534
+ getWorldQuaternion(source, this.__worldQuaternion);
535
+ this._worldQuaternionInverted.copy(this.__worldQuaternion).invert();
536
+ getWorldScale(this.gameObject, this._worldScale);
537
+ if (!this.worldspace && this._container && this.gameObject?.parent) {
183
538
  const scale = getWorldScale(this.gameObject.parent);
184
539
  scale.x = 1 / scale.x;
185
540
  scale.y = 1 / scale.y;
186
541
  scale.z = 1 / scale.z;
187
- // console.log(scale);
188
- // this._container.scale.copy(scale);
189
- // // this._container.updateMatrix();
190
- // // this._container.updateMatrixWorld();
191
- // // // set scale to 1
192
542
  this._container.matrix.identity();
193
543
  this._container.matrix.scale(scale);
194
- // this._container.matrixWorld.copy(this._container.matrix);
195
544
  }
196
- // this._system.time
197
- // this._system.duration = this.main.duration;
198
545
  this.emission.system = this;
199
- this.shape.update(this.context, this.main.simulationSpace, this.gameObject);
546
+ const dt = this.deltaTime;
547
+ this._interface.update();
548
+ this.shape.update(this, this.context, this.main.simulationSpace, this.gameObject);
200
549
  this.noise.update(this.context);
201
- this._system.update(this.context.time.deltaTime * this.main.simulationSpeed);
202
- this._time += this.context.time.deltaTime;
550
+ this.velocityOverLifetime.update(this);
551
+ this._batchSystem?.update(dt);
552
+ this._time += dt;
203
553
  if (this._time > this.duration)
204
554
  this._time = 0;
205
555
  }
@@ -222,154 +572,19 @@ __decorate([
222
572
  __decorate([
223
573
  serializeable(NoiseModule)
224
574
  ], ParticleSystem.prototype, "noise", void 0);
225
- class MinMaxCurveSpan {
226
- time;
227
- curve;
228
- multiplier = 1;
229
- constructor(minMaxCurve, multiplier = 1) {
230
- this.time = Context.Current.time;
231
- this.curve = minMaxCurve;
232
- this.multiplier = multiplier;
233
- }
234
- /** called by nebula */
235
- getValue(lerp) {
236
- const res = this.curve.evaluate(this.time.time, lerp) * this.multiplier;
237
- return res;
238
- }
239
- }
240
- class CustomBehaviour extends Behaviour {
241
- }
242
- class MinMaxCurveBehaviour extends CustomBehaviour {
243
- startCurve;
244
- startMultiplier = 1;
245
- constructor(startCurve, startMultiplier = 1) {
246
- super();
247
- this.startCurve = startCurve;
248
- this.startMultiplier = startMultiplier;
249
- }
250
- }
251
- class SizeBehaviour extends MinMaxCurveBehaviour {
252
- sizeOverLifetimeModule;
253
- cameraScale = 1;
254
- applyBehaviour(particle, _deltaTime, _index) {
255
- if (particle.target.type === "Sprite") {
256
- particle.radius = 1 / this.cameraScale;
257
- }
258
- else
259
- particle.radius = 1;
260
- // particle.target.scale.set(1,1,1);
261
- if (this.sizeOverLifetimeModule?.enabled) {
262
- const time = particle.age / particle.life;
263
- const scaleVector = particle.target.scale;
264
- this.sizeOverLifetimeModule.evaluate?.call(this.sizeOverLifetimeModule, time, scaleVector);
265
- // scaleVector.set(.1, .1, .1)
266
- particle.scale = particle.start_scale * scaleVector.x;
267
- // console.log(time, particle.scale);
268
- }
269
- }
270
- initialize(particle) {
271
- particle.scale = this.startCurve.evaluate(0, Math.random()); // * this.startMultiplier;
272
- particle.start_scale = particle.scale;
273
- }
274
- }
275
- class GradientBehaviour extends CustomBehaviour {
276
- startGradient;
277
- gradient;
278
- constructor(startGradient, gradient) {
279
- super();
280
- this.startGradient = startGradient;
281
- this.gradient = gradient;
282
- }
283
- /** called from nebula */
284
- applyBehaviour(target, _deltaTime, _index) {
285
- // console.log(target, time, index)
286
- if (target instanceof Particle) {
287
- if (this.gradient) {
288
- const t = target.age / target.life;
289
- const ev = this.gradient.evaluate(t);
290
- const startColor = target.color_start;
291
- target.color.r = startColor.r * ev.r;
292
- target.color.g = startColor.g * ev.g;
293
- target.color.b = startColor.b * ev.b;
294
- target.alpha = ev.alpha * target.alpha_start;
295
- }
296
- }
297
- }
298
- id = Symbol('gradientId');
299
- _internalId = 0;
300
- /** called from nebula */
301
- initialize(particle) {
302
- // console.log(particle);
303
- // const context = Context.Current;
304
- // const time = context.time.time;
305
- const ev = this.startGradient.evaluate(Math.random());
306
- particle.color.r = ev.r;
307
- particle.color.g = ev.g;
308
- particle.color.b = ev.b;
309
- particle.alpha = ev.alpha;
310
- particle.age = 0;
311
- particle.color_start = { r: ev.r, g: ev.g, b: ev.b };
312
- particle.alpha_start = ev.alpha;
313
- particle.useColor = true;
314
- particle.useAlpha = true;
315
- if (particle[this.id] === undefined)
316
- particle[this.id] = this._internalId++;
317
- }
318
- }
319
- class VelocityBehaviour extends CustomBehaviour {
320
- container;
321
- shape;
322
- noise;
323
- startSpeed;
324
- startMultiplier = 1;
325
- gravity;
326
- gravityModifierMultiplier = 1;
327
- downDirection = new Vector3();
328
- _temp = new Vector3();
329
- constructor(container, shape, noise, startCurve, startMultiplier) {
330
- super();
331
- this.container = container;
332
- this.shape = shape;
333
- this.noise = noise;
334
- this.startSpeed = startCurve;
335
- this.startMultiplier = startMultiplier;
336
- }
337
- applyBehaviour(target, deltaTime, index) {
338
- if (target instanceof Particle) {
339
- // target.velocity.x = target.velocity_start.x;
340
- // target.velocity.y = target.velocity_start.y;
341
- // target.velocity.z = target.velocity_start.z;
342
- if (target.gravity !== 0 && this.gravity) {
343
- // get world down vector
344
- this._temp.copy(this.downDirection);
345
- this._temp.multiplyScalar(target.gravity * deltaTime);
346
- target.velocity.add(this._temp);
347
- }
348
- if (this.noise) {
349
- this.noise.applyNoise(index, target.position, target.velocity, deltaTime, target.age, target.life);
350
- }
351
- }
352
- }
353
- initialize(particle) {
354
- const dir = this.shape.getDirection(particle.position);
355
- // dir.applyQuaternion(quat);
356
- const speed = this.startSpeed.evaluate(0, Math.random()) * this.startMultiplier;
357
- particle.velocity.x = dir.x * speed;
358
- particle.velocity.y = dir.y * speed;
359
- particle.velocity.z = dir.z * speed;
360
- if (!particle.velocity_start)
361
- particle.velocity_start = {};
362
- particle.velocity_start.x = particle.velocity.x;
363
- particle.velocity_start.y = particle.velocity.y;
364
- particle.velocity_start.z = particle.velocity.z;
365
- if (this.gravity) {
366
- particle.gravity = this.gravity.evaluate(Math.random(), Math.random()) * 9.81;
367
- }
368
- else {
369
- particle.gravity = 0;
370
- }
371
- const quat = getWorldQuaternion(this.container);
372
- this.downDirection.set(0, -1, 0).applyQuaternion(quat);
373
- }
374
- }
575
+ __decorate([
576
+ serializeable(VelocityOverLifetimeModule)
577
+ ], ParticleSystem.prototype, "velocityOverLifetime", void 0);
578
+ __decorate([
579
+ serializeable(LimitVelocityOverLifetimeModule)
580
+ ], ParticleSystem.prototype, "limitVelocityOverLifetime", void 0);
581
+ __decorate([
582
+ serializeable(TextureSheetAnimationModule)
583
+ ], ParticleSystem.prototype, "textureSheetAnimation", void 0);
584
+ __decorate([
585
+ serializeable(RotationOverLifetimeModule)
586
+ ], ParticleSystem.prototype, "rotationOverLifetime", void 0);
587
+ __decorate([
588
+ serializeable(RotationBySpeedModule)
589
+ ], ParticleSystem.prototype, "rotationBySpeed", void 0);
375
590
  //# sourceMappingURL=ParticleSystem.js.map