@needle-tools/engine 2.42.0-pre → 2.43.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 (51) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/needle-engine.d.ts +130 -40
  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_three_utils.d.ts +1 -0
  10. package/lib/engine/engine_three_utils.js +10 -0
  11. package/lib/engine/engine_three_utils.js.map +1 -1
  12. package/lib/engine/engine_time.js +2 -0
  13. package/lib/engine/engine_time.js.map +1 -1
  14. package/lib/engine/extensions/NEEDLE_techniques_webgl.js +42 -0
  15. package/lib/engine/extensions/NEEDLE_techniques_webgl.js.map +1 -1
  16. package/lib/engine-components/Animation.js +9 -1
  17. package/lib/engine-components/Animation.js.map +1 -1
  18. package/lib/engine-components/AnimatorController.js +4 -1
  19. package/lib/engine-components/AnimatorController.js.map +1 -1
  20. package/lib/engine-components/Camera.d.ts +3 -0
  21. package/lib/engine-components/Camera.js +17 -9
  22. package/lib/engine-components/Camera.js.map +1 -1
  23. package/lib/engine-components/ParticleSystem.d.ts +21 -7
  24. package/lib/engine-components/ParticleSystem.js +519 -246
  25. package/lib/engine-components/ParticleSystem.js.map +1 -1
  26. package/lib/engine-components/ParticleSystemBehaviours.d.ts +0 -0
  27. package/lib/engine-components/ParticleSystemBehaviours.js +2 -0
  28. package/lib/engine-components/ParticleSystemBehaviours.js.map +1 -0
  29. package/lib/engine-components/ParticleSystemModules.d.ts +83 -16
  30. package/lib/engine-components/ParticleSystemModules.js +284 -49
  31. package/lib/engine-components/ParticleSystemModules.js.map +1 -1
  32. package/lib/engine-components/codegen/components.d.ts +4 -0
  33. package/lib/engine-components/codegen/components.js +4 -0
  34. package/lib/engine-components/codegen/components.js.map +1 -1
  35. package/lib/engine-components/js-extensions/RGBAColor.d.ts +1 -0
  36. package/lib/engine-components/js-extensions/RGBAColor.js +7 -0
  37. package/lib/engine-components/js-extensions/RGBAColor.js.map +1 -1
  38. package/package.json +2 -1
  39. package/src/engine/codegen/register_types.js +16 -0
  40. package/src/engine/engine_element_loading.ts +22 -5
  41. package/src/engine/engine_three_utils.ts +11 -2
  42. package/src/engine/engine_time.ts +1 -0
  43. package/src/engine/extensions/NEEDLE_techniques_webgl.ts +43 -1
  44. package/src/engine-components/Animation.ts +7 -1
  45. package/src/engine-components/AnimatorController.ts +5 -1
  46. package/src/engine-components/Camera.ts +17 -10
  47. package/src/engine-components/ParticleSystem.ts +600 -274
  48. package/src/engine-components/ParticleSystemBehaviours.ts +0 -0
  49. package/src/engine-components/ParticleSystemModules.ts +263 -51
  50. package/src/engine-components/codegen/components.ts +4 -0
  51. package/src/engine-components/js-extensions/RGBAColor.ts +7 -0
@@ -1,11 +1,12 @@
1
1
  import { init } from "@dimforge/rapier3d-compat";
2
2
  import * as THREE from "three";
3
- import { Color, Matrix4, Object3D, Vector3 } from "three";
3
+ import { Color, Matrix4, Object3D, PointLightShadow, Quaternion, Vector3 } from "three";
4
4
  import { Mathf } from "../engine/engine_math";
5
5
  import { serializeable } from "../engine/engine_serialization";
6
6
  import { RGBAColor } from "./js-extensions/RGBAColor";
7
7
  import { AnimationCurve } from "./AnimationCurve";
8
8
  import { Vec3 } from "../engine/engine_types";
9
+ import { EmitterShape, FrameOverLife, Particle, ShapeJSON } from "three.quarks";
9
10
 
10
11
  declare type Color4 = { r: number, g: number, b: number, a: number };
11
12
  declare type ColorKey = { time: number, color: Color4 };
@@ -17,6 +18,9 @@ export interface IParticleSystem {
17
18
  get time(): number;
18
19
  get duration(): number;
19
20
  readonly main: MainModule;
21
+ get container(): Object3D;
22
+ get worldQuaternion(): Quaternion;
23
+ get worldQuaternionInverted(): Quaternion;
20
24
  }
21
25
 
22
26
  export enum ParticleSystemRenderMode {
@@ -165,14 +169,14 @@ export class MinMaxCurve {
165
169
  case ParticleSystemCurveMode.Constant:
166
170
  return this.constant;
167
171
  case ParticleSystemCurveMode.Curve:
168
- t01 %= this.curve!.duration;
169
- return this.curve!.evaluate(t01);
172
+ t01 = Mathf.clamp01(t01);
173
+ return this.curve!.evaluate(t01) * this.curveMultiplier!;
170
174
  case ParticleSystemCurveMode.TwoCurves:
171
175
  const t1 = t01 * this.curveMin!.duration;
172
176
  const t2 = t01 * this.curveMax!.duration;
173
- return Mathf.lerp(this.curveMin!.evaluate(t1), this.curveMax!.evaluate(t2), t % 1);
177
+ return Mathf.lerp(this.curveMin!.evaluate(t1), this.curveMax!.evaluate(t2), t % 1) * this.curveMultiplier!;
174
178
  case ParticleSystemCurveMode.TwoConstants:
175
- return Mathf.lerp(this.constantMin, this.constantMax, t % 1);
179
+ return Mathf.lerp(this.constantMin, this.constantMax, t % 1)
176
180
  default:
177
181
  this.curveMax!.evaluate(t01) * this.curveMultiplier!;
178
182
  break;
@@ -208,7 +212,8 @@ export class MinMaxGradient {
208
212
  this.gradient.evaluate(t01, MinMaxGradient._temp);
209
213
  return MinMaxGradient._temp
210
214
  case ParticleSystemGradientMode.TwoColors:
211
- return MinMaxGradient._temp.lerpColors(this.colorMin, this.colorMax, t);
215
+ const col1 = MinMaxGradient._temp.lerpColors(this.colorMin, this.colorMax, t);
216
+ return col1;
212
217
  case ParticleSystemGradientMode.TwoGradients:
213
218
  const t2 = Math.random();
214
219
  this.gradientMin.evaluate(t2, MinMaxGradient._temp);
@@ -374,23 +379,9 @@ export class EmissionModule {
374
379
  system!: IParticleSystem;
375
380
  get time() { return this.system.time; }
376
381
 
377
- private _summed: number = 0;
378
- // private _didEmit: boolean = false;
379
-
380
- /** called by nebula */
381
- init() {
382
- }
383
-
384
- /** called by nebula */
385
- getValue(deltaTime: number) {
386
- if (this.system.currentParticles >= this.system.maxParticles)
387
- return 0;
388
- if (!this.enabled) return 0;
389
- let count = this.rateOverTime.evaluate(this.time / this.system.duration, Math.random());
390
- this._summed += count * deltaTime;
391
- let amount = Math.floor(this._summed);
392
- this._summed -= amount;
393
382
 
383
+ getBurst() {
384
+ let amount = 0;
394
385
  if (this.burstCount > 0) {
395
386
  for (let i = 0; i < this.burstCount; i++) {
396
387
  const burst = this.bursts[i];
@@ -401,9 +392,7 @@ export class EmissionModule {
401
392
  amount += Math.round(burst.run(this.time));
402
393
  }
403
394
  }
404
-
405
- // dont emit more than we are allowed to
406
- return amount;//Mathf.clamp(amount, 0, this.system.maxParticles - this.system.currentParticles);
395
+ return amount;
407
396
  }
408
397
  }
409
398
 
@@ -420,18 +409,26 @@ export class SizeOverLifetimeModule {
420
409
  size!: MinMaxCurve;
421
410
  sizeMultiplier!: number;
422
411
  @serializeable(MinMaxCurve)
423
- sizeX!: MinMaxCurve;
424
- sizeXMultiplier!: number;
412
+ x!: MinMaxCurve;
413
+ xMultiplier!: number;
425
414
  @serializeable(MinMaxCurve)
426
- sizeY!: MinMaxCurve;
427
- sizeYMultiplier!: number;
415
+ y!: MinMaxCurve;
416
+ yMultiplier!: number;
428
417
  @serializeable(MinMaxCurve)
429
- sizeZ!: MinMaxCurve;
430
- sizeZMultiplier!: number;
418
+ z!: MinMaxCurve;
419
+ zMultiplier!: number;
431
420
 
432
421
  private _time: number = 0;
422
+ private _temp = new Vector3();
423
+
424
+ evaluate(t01: number, target?: Vec3) {
425
+ if (!target) target = this._temp;
426
+
427
+ if (!this.enabled) {
428
+ target.x = target.y = target.z = 1;
429
+ return target;
430
+ }
433
431
 
434
- evaluate(t01: number, target: Vec3) {
435
432
  if (!this.separateAxes) {
436
433
  const scale = this.size.evaluate(t01) * this.sizeMultiplier;
437
434
  target.x = scale;
@@ -439,15 +436,31 @@ export class SizeOverLifetimeModule {
439
436
  // target.z = scale;
440
437
  }
441
438
  else {
442
- target.x = this.sizeX.evaluate(this._time) * this.sizeXMultiplier;
443
- // target.y = this.sizeY.evaluate(this._time) * this.sizeYMultiplier;
444
- // target.z = this.sizeZ.evaluate(this._time) * this.sizeZMultiplier;
439
+ target.x = this.x.evaluate(t01) * this.xMultiplier;
440
+ target.y = this.y.evaluate(t01) * this.yMultiplier;
441
+ target.z = this.z.evaluate(t01) * this.zMultiplier;
445
442
  }
446
443
  return target;
447
444
  }
448
445
  }
449
446
 
450
- export class ShapeModule {
447
+ export class ShapeModule implements EmitterShape {
448
+
449
+ get type(): string {
450
+ return ParticleSystemShapeType[this.shapeType];
451
+ }
452
+
453
+ initialize(particle: Particle): void {
454
+ this.getPosition();
455
+ particle.position.copy(this._vector);
456
+ }
457
+ toJSON(): ShapeJSON {
458
+ return this;
459
+ }
460
+ clone(): EmitterShape {
461
+ return new ShapeModule();
462
+ }
463
+
451
464
  @serializeable()
452
465
  shapeType: ParticleSystemShapeType = ParticleSystemShapeType.Box;
453
466
  @serializeable()
@@ -502,7 +515,6 @@ export class ShapeModule {
502
515
  get vector() {
503
516
  return this._vector;
504
517
  }
505
- /** called by nebula */
506
518
  getPosition(): void {
507
519
  switch (this.shapeType) {
508
520
  case ParticleSystemShapeType.Box:
@@ -513,6 +525,9 @@ export class ShapeModule {
513
525
  case ParticleSystemShapeType.Sphere:
514
526
  randomSpherePoint(this.position.x, this.position.y, this.position.z, this.radius, this.radiusThickness, this.arc, this._vector);
515
527
  break;
528
+ default:
529
+ this._vector.set(0, 0, 0);
530
+ break;
516
531
  // case ParticleSystemShapeType.Hemisphere:
517
532
  // randomSpherePoint(this.position.x, this.position.y, this.position.z, this.radius, this.radiusThickness, 180, this._vector);
518
533
  // break;
@@ -559,6 +574,8 @@ function randomSpherePoint(x0: number, y0: number, z0: number, radius: number, t
559
574
 
560
575
  import { createNoise4D, NoiseFunction4D } from 'simplex-noise';
561
576
  import { Context } from "../engine/engine_setup";
577
+ import { getWorldQuaternion } from "../engine/engine_three_utils";
578
+ import { Gizmos } from "../engine/engine_gizmos";
562
579
 
563
580
  export class NoiseModule {
564
581
  @serializeable()
@@ -626,34 +643,229 @@ export class NoiseModule {
626
643
 
627
644
  /** nebula implementations: */
628
645
  private _temp: Vector3 = new Vector3();
629
- applyNoise(index: number, pos: Vec3, vel: Vec3, deltaTime: number, age: number, life: number) {
646
+ apply(_index: number, pos: Vec3, vel: Vec3, _deltaTime: number, age: number, life: number) {
630
647
  if (!this.enabled) return;
631
648
  if (!this._noise) {
632
649
  this._noise = createNoise4D(() => 0);
633
650
  }
634
- const t = age / life;
635
- const dt = Context.Current.time.deltaTime;
636
651
  const temp = this._temp.set(pos.x, pos.y, pos.z).multiplyScalar(this.frequency);
637
652
  const nx = this._noise(temp.x, temp.y, temp.z, this._time);
638
- const ny = this._noise(temp.x, temp.y, temp.z, this._time + .2);
639
- const nz = this._noise(temp.x, temp.y, temp.z, this._time + .5);
640
- this._temp.set(nx, ny, nz).normalize();
653
+ const ny = this._noise(temp.x, temp.y, temp.z, this._time + .3);
654
+ const nz = this._noise(temp.x, temp.y, temp.z, this._time + 1);
655
+ this._temp.set(nx, ny, nz).normalize()
641
656
 
657
+ const t = age / life;
642
658
  let strengthFactor = this.positionAmount.evaluate(t);
643
659
  if (!this.separateAxes) {
644
- if (this.strengthX)
645
- strengthFactor *= this.strengthX.evaluate(t, index * 1.1);
646
- else strengthFactor *= this.strengthMultiplier;
647
- strengthFactor *= deltaTime;
660
+ if (this.strengthX) {
661
+ strengthFactor *= this.strengthX.evaluate(t) * Math.PI;
662
+ }
663
+ // strengthFactor *= this.strengthMultiplier;
664
+ // strengthFactor *= deltaTime;
648
665
  this._temp.multiplyScalar(strengthFactor);
649
666
  }
650
- if (this.separateAxes) {
651
- this._temp.x *= strengthFactor * deltaTime * this.strengthXMultiplier
652
- this._temp.y *= strengthFactor * deltaTime * this.strengthYMultiplier;
653
- this._temp.z *= strengthFactor * deltaTime * this.strengthZMultiplier;
667
+ else {
668
+ this._temp.x *= strengthFactor * this.strengthXMultiplier
669
+ this._temp.y *= strengthFactor * this.strengthYMultiplier;
670
+ this._temp.z *= strengthFactor * this.strengthZMultiplier;
671
+ }
672
+ // this._temp.setLength(strengthFactor * deltaTime);
673
+ vel.x += this._temp.x;
674
+ vel.y += this._temp.y;
675
+ vel.z += this._temp.z;
676
+ }
677
+ }
678
+
679
+ export class TrailModule {
680
+
681
+ @serializeable()
682
+ enabled!: boolean;
683
+ }
684
+
685
+ export class VelocityOverLifetimeModule {
686
+ @serializeable()
687
+ enabled!: boolean;
688
+
689
+ /* orbital settings */
690
+
691
+
692
+ @serializeable()
693
+ space: ParticleSystemSimulationSpace = ParticleSystemSimulationSpace.Local;
694
+
695
+ @serializeable(MinMaxCurve)
696
+ speedModifier!: MinMaxCurve;
697
+ @serializeable()
698
+ speedModifierMultiplier!: number;
699
+ @serializeable(MinMaxCurve)
700
+ x!: MinMaxCurve;
701
+ @serializeable()
702
+ xMultiplier!: number;
703
+ @serializeable(MinMaxCurve)
704
+ y!: MinMaxCurve;
705
+ @serializeable()
706
+ yMultiplier!: number;
707
+ @serializeable(MinMaxCurve)
708
+ z!: MinMaxCurve;
709
+ @serializeable()
710
+ zMultiplier!: number;
711
+
712
+ private _system?: IParticleSystem;
713
+ // private _worldRotation: Quaternion = new Quaternion();
714
+
715
+ update(system: IParticleSystem) {
716
+ this._system = system;
717
+ }
718
+
719
+ private _temp: Vector3 = new Vector3();
720
+
721
+ apply(_index: number, _pos: Vec3, vel: Vec3, _dt: number, age: number, life: number) {
722
+ if (!this.enabled) return;
723
+ const t = age / life;
724
+
725
+ const speed = this.speedModifier.evaluate(t) * this.speedModifierMultiplier;
726
+ const x = this.x.evaluate(t) * speed;
727
+ const y = this.y.evaluate(t) * speed;
728
+ const z = this.z.evaluate(t) * speed;
729
+ this._temp.set(-x, y, z);
730
+ if (this._system) {
731
+ if (this.space === ParticleSystemSimulationSpace.World) {
732
+ this._temp.applyQuaternion(this._system.worldQuaternionInverted);
733
+ }
734
+ if (this._system.main.simulationSpace === ParticleSystemSimulationSpace.World) {
735
+ this._temp.applyQuaternion(this._system.worldQuaternion);
736
+ }
654
737
  }
655
738
  vel.x += this._temp.x;
656
739
  vel.y += this._temp.y;
657
740
  vel.z += this._temp.z;
658
741
  }
742
+ }
743
+
744
+
745
+
746
+ enum ParticleSystemAnimationTimeMode {
747
+ Lifetime,
748
+ Speed,
749
+ FPS,
750
+ }
751
+
752
+ enum ParticleSystemAnimationMode {
753
+ Grid,
754
+ Sprites,
755
+ }
756
+
757
+ enum ParticleSystemAnimationRowMode {
758
+ Custom,
759
+ Random,
760
+ MeshIndex,
761
+ }
762
+
763
+ enum ParticleSystemAnimationType {
764
+ WholeSheet,
765
+ SingleRow,
766
+ }
767
+
768
+ export class TextureSheetAnimationModule {
769
+
770
+ @serializeable()
771
+ animation!: ParticleSystemAnimationType;
772
+
773
+ @serializeable()
774
+ enabled!: boolean;
775
+
776
+ @serializeable()
777
+ cycleCount!: number;
778
+
779
+ @serializeable(MinMaxCurve)
780
+ frameOverTime!: MinMaxCurve;
781
+ @serializeable()
782
+ frameOverTimeMultiplier!: number;
783
+
784
+ @serializeable()
785
+ numTilesX!: number;
786
+ @serializeable()
787
+ numTilesY!: number;
788
+
789
+ @serializeable(MinMaxCurve)
790
+ startFrame!: MinMaxCurve;
791
+ @serializeable()
792
+ startFrameMultiplier!: number;
793
+
794
+ @serializeable()
795
+ rowMode!: ParticleSystemAnimationRowMode;
796
+ @serializeable()
797
+ rowIndex!: number;
798
+
799
+ @serializeable()
800
+ spriteCount!: number;
801
+
802
+ @serializeable()
803
+ timeMode!: ParticleSystemAnimationTimeMode;
804
+
805
+ private sampleOnceAtStart(): boolean {
806
+ if (this.timeMode === ParticleSystemAnimationTimeMode.Lifetime) {
807
+ switch (this.frameOverTime.mode) {
808
+ case ParticleSystemCurveMode.Constant:
809
+ case ParticleSystemCurveMode.TwoConstants:
810
+ return true;
811
+ }
812
+ }
813
+ return false;
814
+ }
815
+
816
+ getStartIndex(): number {
817
+ if (this.sampleOnceAtStart()) {
818
+ return this.frameOverTime.evaluate(Math.random())
819
+ }
820
+ return 0;
821
+ }
822
+
823
+ evaluate(t01: number): number | undefined {
824
+ if (this.sampleOnceAtStart()) {
825
+ return;
826
+ }
827
+ return this.getIndex(t01);
828
+ }
829
+
830
+ private getIndex(t01: number): number {
831
+ const tiles = this.numTilesX * this.numTilesY;
832
+ // let pos = t01 * this.cycleCount;
833
+ let index = this.frameOverTime.evaluate(t01 % 1);
834
+ index *= this.frameOverTimeMultiplier;
835
+ index *= tiles;
836
+ index = index % tiles;
837
+ index = Math.floor(index);
838
+ // console.log(index);
839
+ return index;
840
+ }
841
+ }
842
+
843
+
844
+ export class RotationOverLifetimeModule {
845
+ @serializeable()
846
+ enabled!: boolean;
847
+
848
+ @serializeable()
849
+ separateAxes!: boolean;
850
+
851
+ @serializeable(MinMaxCurve)
852
+ x!: MinMaxCurve;
853
+ @serializeable()
854
+ xMultiplier!: number;
855
+ @serializeable(MinMaxCurve)
856
+ y!: MinMaxCurve;
857
+ @serializeable()
858
+ yMultiplier!: number;
859
+ @serializeable(MinMaxCurve)
860
+ z!: MinMaxCurve;
861
+ @serializeable()
862
+ zMultiplier!: number;
863
+
864
+ evaluate(t01: number): number {
865
+ if (!this.enabled) return 0;
866
+ if (!this.separateAxes) {
867
+ return this.z.evaluate(t01) * -1;
868
+ }
869
+ return 0;
870
+ }
659
871
  }
@@ -60,6 +60,10 @@ export { ColorOverLifetimeModule } from "../ParticleSystemModules";
60
60
  export { SizeOverLifetimeModule } from "../ParticleSystemModules";
61
61
  export { ShapeModule } from "../ParticleSystemModules";
62
62
  export { NoiseModule } from "../ParticleSystemModules";
63
+ export { TrailModule } from "../ParticleSystemModules";
64
+ export { VelocityOverLifetimeModule } from "../ParticleSystemModules";
65
+ export { TextureSheetAnimationModule } from "../ParticleSystemModules";
66
+ export { RotationOverLifetimeModule } from "../ParticleSystemModules";
63
67
  export { PlayerColor } from "../PlayerColor";
64
68
  export { ReflectionProbe } from "../ReflectionProbe";
65
69
  export { FieldWithDefault } from "../Renderer";
@@ -32,6 +32,13 @@ export class RGBAColor extends Color {
32
32
  return super.lerp(color, alpha);
33
33
  }
34
34
 
35
+ lerpColors(color1: Color, color2: Color, alpha: number): this {
36
+ const rgba1 = color1 as RGBAColor;
37
+ const rgba2 = color2 as RGBAColor;
38
+ if(rgba1.alpha && rgba2.alpha) this.alpha = Mathf.lerp(rgba1.alpha, rgba2.alpha, alpha);
39
+ return super.lerpColors(color1, color2, alpha);
40
+ }
41
+
35
42
  multiply(color: Color): this {
36
43
  const rgba = color as RGBAColor;
37
44
  if(rgba.alpha) this.alpha = this.alpha * rgba.alpha;