@needle-tools/engine 2.41.0-pre → 2.42.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 (55) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/needle-engine.d.ts +100 -40
  3. package/dist/needle-engine.js +367 -367
  4. package/dist/needle-engine.js.map +3 -3
  5. package/dist/needle-engine.min.js +37 -37
  6. package/dist/needle-engine.min.js.map +3 -3
  7. package/lib/engine/engine_element.js +1 -1
  8. package/lib/engine/engine_element.js.map +1 -1
  9. package/lib/engine/engine_element_loading.js +6 -1
  10. package/lib/engine/engine_element_loading.js.map +1 -1
  11. package/lib/engine/engine_gizmos.d.ts +8 -22
  12. package/lib/engine/engine_gizmos.js +37 -3
  13. package/lib/engine/engine_gizmos.js.map +1 -1
  14. package/lib/engine/engine_setup.d.ts +3 -0
  15. package/lib/engine/engine_setup.js +15 -0
  16. package/lib/engine/engine_setup.js.map +1 -1
  17. package/lib/engine/engine_three_utils.d.ts +16 -1
  18. package/lib/engine/engine_three_utils.js +94 -54
  19. package/lib/engine/engine_three_utils.js.map +1 -1
  20. package/lib/engine/engine_types.d.ts +6 -0
  21. package/lib/engine/engine_types.js.map +1 -1
  22. package/lib/engine-components/AnimationCurve.js +2 -2
  23. package/lib/engine-components/AnimationCurve.js.map +1 -1
  24. package/lib/engine-components/BoxHelperComponent.js +9 -10
  25. package/lib/engine-components/BoxHelperComponent.js.map +1 -1
  26. package/lib/engine-components/ParticleSystem.d.ts +24 -10
  27. package/lib/engine-components/ParticleSystem.js +136 -41
  28. package/lib/engine-components/ParticleSystem.js.map +1 -1
  29. package/lib/engine-components/ParticleSystemModules.d.ts +40 -6
  30. package/lib/engine-components/ParticleSystemModules.js +103 -21
  31. package/lib/engine-components/ParticleSystemModules.js.map +1 -1
  32. package/lib/engine-components/ReflectionProbe.js +29 -11
  33. package/lib/engine-components/ReflectionProbe.js.map +1 -1
  34. package/lib/engine-components/Renderer.d.ts +1 -0
  35. package/lib/engine-components/Renderer.js +4 -2
  36. package/lib/engine-components/Renderer.js.map +1 -1
  37. package/lib/engine-components/codegen/components.d.ts +1 -0
  38. package/lib/engine-components/codegen/components.js +1 -0
  39. package/lib/engine-components/codegen/components.js.map +1 -1
  40. package/package.json +2 -2
  41. package/src/engine/codegen/register_types.js +4 -0
  42. package/src/engine/dist/engine_three_utils.js +279 -0
  43. package/src/engine/engine_element.ts +1 -1
  44. package/src/engine/engine_element_loading.ts +5 -1
  45. package/src/engine/engine_gizmos.ts +45 -8
  46. package/src/engine/engine_setup.ts +25 -2
  47. package/src/engine/engine_three_utils.ts +103 -62
  48. package/src/engine/engine_types.ts +8 -1
  49. package/src/engine-components/AnimationCurve.ts +2 -2
  50. package/src/engine-components/BoxHelperComponent.ts +12 -15
  51. package/src/engine-components/ParticleSystem.ts +151 -75
  52. package/src/engine-components/ParticleSystemModules.ts +127 -24
  53. package/src/engine-components/ReflectionProbe.ts +37 -13
  54. package/src/engine-components/Renderer.ts +4 -2
  55. package/src/engine-components/codegen/components.ts +1 -0
@@ -11,6 +11,24 @@ declare type Color4 = { r: number, g: number, b: number, a: number };
11
11
  declare type ColorKey = { time: number, color: Color4 };
12
12
  declare type AlphaKey = { time: number, alpha: number };
13
13
 
14
+ export interface IParticleSystem {
15
+ get currentParticles(): number;
16
+ get maxParticles(): number;
17
+ get time(): number;
18
+ get duration(): number;
19
+ readonly main: MainModule;
20
+ }
21
+
22
+ export enum ParticleSystemRenderMode {
23
+ Billboard = 0,
24
+ // Stretch = 1,
25
+ // HorizontalBillboard = 2,
26
+ // VerticalBillboard = 3,
27
+ Mesh = 4,
28
+ // None = 5,
29
+ }
30
+
31
+
14
32
  export class Gradient {
15
33
  @serializeable()
16
34
  alphaKeys!: Array<AlphaKey>;
@@ -178,7 +196,8 @@ export class MinMaxGradient {
178
196
  @serializeable(Gradient)
179
197
  gradientMax!: Gradient;
180
198
 
181
- private _temp: RGBAColor = new RGBAColor(0, 0, 0, 1);
199
+ private static _temp: RGBAColor = new RGBAColor(0, 0, 0, 1);
200
+ private static _temp2: RGBAColor = new RGBAColor(0, 0, 0, 1);
182
201
 
183
202
  evaluate(t01: number, lerpFactor?: number): RGBAColor {
184
203
  const t = lerpFactor === undefined ? Math.random() : lerpFactor;
@@ -186,15 +205,21 @@ export class MinMaxGradient {
186
205
  case ParticleSystemGradientMode.Color:
187
206
  return this.color;
188
207
  case ParticleSystemGradientMode.Gradient:
189
- this.gradient.evaluate(t01, this._temp);
190
- return this._temp
208
+ this.gradient.evaluate(t01, MinMaxGradient._temp);
209
+ return MinMaxGradient._temp
191
210
  case ParticleSystemGradientMode.TwoColors:
192
- return this._temp.lerpColors(this.colorMin, this.colorMax, t);
211
+ return MinMaxGradient._temp.lerpColors(this.colorMin, this.colorMax, t);
212
+ case ParticleSystemGradientMode.TwoGradients:
213
+ const t2 = Math.random();
214
+ this.gradientMin.evaluate(t2, MinMaxGradient._temp);
215
+ this.gradientMax.evaluate(t2, MinMaxGradient._temp2);
216
+ return MinMaxGradient._temp.lerp(MinMaxGradient._temp2, t);
217
+
193
218
  }
194
219
  // console.warn("Not implemented", ParticleSystemGradientMode[this.mode]);
195
- this._temp.set(0xff00ff)
196
- this._temp.alpha = 1;
197
- return this._temp;
220
+ MinMaxGradient._temp.set(0xff00ff)
221
+ MinMaxGradient._temp.alpha = 1;
222
+ return MinMaxGradient._temp;
198
223
  }
199
224
  }
200
225
 
@@ -262,23 +287,93 @@ export class MainModule {
262
287
  useUnscaledTime!: boolean;
263
288
  }
264
289
 
290
+
291
+ export class ParticleBurst {
292
+ cycleCount!: number;
293
+ maxCount!: number;
294
+ minCount!: number;
295
+ probability!: number;
296
+ repeatInterval!: number;
297
+ time!: number;
298
+ count!: {
299
+ constant: number;
300
+ constantMax: number;
301
+ constantMin: number;
302
+ curve?: AnimationCurve;
303
+ curveMax?: AnimationCurve;
304
+ curveMin?: AnimationCurve;
305
+ curveMultiplier?: number;
306
+ mode: ParticleSystemCurveMode;
307
+ }
308
+
309
+
310
+ private _performed: number = 0;
311
+
312
+
313
+ reset() {
314
+ this._performed = 0;
315
+ }
316
+ run(time: number): number {
317
+ if (time <= this.time) {
318
+ this.reset();
319
+ return 0;
320
+ }
321
+ let amount = 0;
322
+ if (this.cycleCount === 0 || this._performed < this.cycleCount) {
323
+ const nextTime = this.time + this.repeatInterval * this._performed;
324
+ if (time >= nextTime) {
325
+ this._performed += 1;
326
+ if (Math.random() < this.probability) {
327
+ switch (this.count.mode) {
328
+ case ParticleSystemCurveMode.Constant:
329
+ amount = this.count.constant;
330
+ break;
331
+ case ParticleSystemCurveMode.TwoConstants:
332
+ amount = Mathf.lerp(this.count.constantMin, this.count.constantMax, Math.random());
333
+ break;
334
+ case ParticleSystemCurveMode.Curve:
335
+ amount = this.count.curve!.evaluate(Math.random());
336
+ break;
337
+ case ParticleSystemCurveMode.TwoCurves:
338
+ const t = Math.random();
339
+ amount = Mathf.lerp(this.count.curveMin!.evaluate(t), this.count.curveMax!.evaluate(t), Math.random());
340
+ break;
341
+ }
342
+ }
343
+ }
344
+ }
345
+ return amount;
346
+ }
347
+ }
348
+
265
349
  export class EmissionModule {
266
- burstCount!: number;
350
+
351
+ @serializeable()
267
352
  enabled!: boolean;
268
353
 
354
+
355
+ get burstCount() {
356
+ return this.bursts?.length ?? 0;
357
+ }
358
+
359
+ @serializeable()
360
+ bursts!: ParticleBurst[];
361
+
269
362
  @serializeable(MinMaxCurve)
270
363
  rateOverTime!: MinMaxCurve;
364
+ @serializeable()
271
365
  rateOverTimeMultiplier!: number;
272
366
 
273
367
  @serializeable(MinMaxCurve)
274
368
  rateOverDistance!: MinMaxCurve;
369
+ @serializeable()
275
370
  rateOverDistanceMultiplier!: number;
276
371
 
277
372
 
278
- currentParticles: number = 0;
279
- maxParticles: number = Infinity;
373
+ /** set from system */
374
+ system!: IParticleSystem;
375
+ get time() { return this.system.time; }
280
376
 
281
- private _time: number = 0;
282
377
  private _summed: number = 0;
283
378
  // private _didEmit: boolean = false;
284
379
 
@@ -288,19 +383,27 @@ export class EmissionModule {
288
383
 
289
384
  /** called by nebula */
290
385
  getValue(deltaTime: number) {
291
- if (this.currentParticles >= this.maxParticles)
386
+ if (this.system.currentParticles >= this.system.maxParticles)
292
387
  return 0;
293
- // if (this._didEmit) return 0;
294
- // this._didEmit = true;
295
- // return 1;
296
-
297
388
  if (!this.enabled) return 0;
298
- const time = this._time += deltaTime;
299
- let count = this.rateOverTime.evaluate(time, Math.random());
389
+ let count = this.rateOverTime.evaluate(this.time / this.system.duration, Math.random());
300
390
  this._summed += count * deltaTime;
301
- const amount = Math.floor(this._summed);
391
+ let amount = Math.floor(this._summed);
302
392
  this._summed -= amount;
303
- return amount;
393
+
394
+ if (this.burstCount > 0) {
395
+ for (let i = 0; i < this.burstCount; i++) {
396
+ const burst = this.bursts[i];
397
+ if (burst.time >= this.time) {
398
+ burst.reset();
399
+ continue;
400
+ }
401
+ amount += Math.round(burst.run(this.time));
402
+ }
403
+ }
404
+
405
+ // dont emit more than we are allowed to
406
+ return amount;//Mathf.clamp(amount, 0, this.system.maxParticles - this.system.currentParticles);
304
407
  }
305
408
  }
306
409
 
@@ -414,7 +517,7 @@ export class ShapeModule {
414
517
  // randomSpherePoint(this.position.x, this.position.y, this.position.z, this.radius, this.radiusThickness, 180, this._vector);
415
518
  // break;
416
519
  }
417
- if(this._space === ParticleSystemSimulationSpace.World) {
520
+ if (this._space === ParticleSystemSimulationSpace.World) {
418
521
  this._vector.applyMatrix4(this._worldSpacePosition);
419
522
  }
420
523
  }
@@ -422,7 +525,7 @@ export class ShapeModule {
422
525
 
423
526
 
424
527
  private _dir: Vector3 = new Vector3();
425
- getDirection(position): Vec3 {
528
+ getDirection(position): Vector3 {
426
529
  switch (this.shapeType) {
427
530
  case ParticleSystemShapeType.Box:
428
531
  return this._dir.set(0, 0, 1);
@@ -540,8 +643,8 @@ export class NoiseModule {
540
643
  if (!this.separateAxes) {
541
644
  if (this.strengthX)
542
645
  strengthFactor *= this.strengthX.evaluate(t, index * 1.1);
543
- strengthFactor *= this.strengthMultiplier;
544
- strengthFactor *= .1;
646
+ else strengthFactor *= this.strengthMultiplier;
647
+ strengthFactor *= deltaTime;
545
648
  this._temp.multiplyScalar(strengthFactor);
546
649
  }
547
650
  if (this.separateAxes) {
@@ -10,11 +10,14 @@ import { getParam } from "../engine/engine_utils";
10
10
  export const debug = getParam("debugreflectionprobe");
11
11
  const disable = getParam("noreflectionprobe");
12
12
 
13
+ const $reflectionProbeKey = Symbol("reflectionProbeKey");
14
+ const $originalMaterial = Symbol("original material");
15
+
13
16
  export class ReflectionProbe extends Behaviour {
14
17
 
15
18
  private static _probes: Map<Context, ReflectionProbe[]> = new Map();
16
19
 
17
- public static get(object: Object3D | null | undefined, context: Context, isAnchor:boolean): ReflectionProbe | null {
20
+ public static get(object: Object3D | null | undefined, context: Context, isAnchor: boolean): ReflectionProbe | null {
18
21
  if (!object || object.isObject3D !== true) return null;
19
22
  if (disable) return null;
20
23
  const probes = ReflectionProbe._probes.get(context);
@@ -91,7 +94,7 @@ export class ReflectionProbe extends Behaviour {
91
94
  // and some need reflection probe and some don't
92
95
  // we need to make sure we don't override the material but use a copy
93
96
 
94
- private static _rendererMaterialsCache: Map<IRenderer, Array<{ orig: Material, copy: Material }>> = new Map();
97
+ private static _rendererMaterialsCache: Map<IRenderer, Array<{ material: Material, copy: Material }>> = new Map();
95
98
 
96
99
  onSet(_rend: IRenderer) {
97
100
  if (disable) return;
@@ -109,22 +112,43 @@ export class ReflectionProbe extends Behaviour {
109
112
  // need to make sure materials are not shared when using reflection probes
110
113
  // otherwise some renderers outside of the probe will be affected or vice versa
111
114
  for (let i = 0; i < _rend.sharedMaterials.length; i++) {
112
- const orig = _rend.sharedMaterials[i];
113
- if (!orig) continue;
114
- if (orig["envMap"] === undefined) continue;
115
+ const material = _rend.sharedMaterials[i];
116
+ if (!material) continue;
117
+ if (material["envMap"] === undefined) continue;
118
+ if (material["envMap"] === this.texture) {
119
+ continue;
120
+ }
115
121
  let cached = rendererCache[i];
116
- let copy = cached?.copy;
117
- if (!cached) {
118
- const clone = orig.clone();
119
- copy = clone;
120
- rendererCache.push({ orig, copy });
121
122
 
122
- copy["__reflection_probe"] = this;
123
- copy["envMap"] = this.texture;
123
+ // make sure we have the currently assigned material cached (and an up to date clone of that)
124
+ if (!cached || cached.material !== material || cached.material.version !== material.version) {
125
+ const clone = material.clone();
126
+
127
+ if (cached) {
128
+ cached.copy = clone;
129
+ cached.material = material;
130
+ }
131
+ else {
132
+ cached = {
133
+ material: material,
134
+ copy: clone
135
+ };
136
+ rendererCache.push(cached);
137
+ }
138
+
139
+ clone[$reflectionProbeKey] = this;
140
+ clone[$originalMaterial] = material;
141
+
142
+ // make sure the reflection probe is assigned
143
+ clone["envMap"] = this.texture;
124
144
 
125
145
  if (debug)
126
146
  console.log("Set reflection", _rend.name, _rend.guid);
127
147
  }
148
+
149
+ /** this is the material that we copied and that has the reflection probe */
150
+ const copy = cached?.copy;
151
+
128
152
  _rend.sharedMaterials[i] = copy;
129
153
  }
130
154
  }
@@ -134,7 +158,7 @@ export class ReflectionProbe extends Behaviour {
134
158
  if (rendererCache) {
135
159
  for (let i = 0; i < rendererCache.length; i++) {
136
160
  const cached = rendererCache[i];
137
- _rend.sharedMaterials[i] = cached.orig;
161
+ _rend.sharedMaterials[i] = cached.material;
138
162
  }
139
163
  }
140
164
  }
@@ -219,6 +219,8 @@ export class Renderer extends Behaviour implements IRenderer {
219
219
  return lm !== null && lm !== undefined;
220
220
  }
221
221
 
222
+ allowProgressiveLoading : boolean = true;
223
+
222
224
  awake() {
223
225
  this.clearInstancingState();
224
226
 
@@ -457,7 +459,7 @@ export class Renderer extends Behaviour implements IRenderer {
457
459
  onBeforeRenderThree(_renderer, _scene, _camera, _geometry, material, _group) {
458
460
 
459
461
  // progressive load before rendering so we only load textures for visible materials
460
- if (!suppressProgressiveLoading && material._didRequestTextureLOD === undefined) {
462
+ if (!suppressProgressiveLoading && material._didRequestTextureLOD === undefined && this.allowProgressiveLoading) {
461
463
  material._didRequestTextureLOD = 0;
462
464
  if (debugProgressiveLoading) {
463
465
  console.log("Load material LOD (with delay)", material.name);
@@ -542,7 +544,7 @@ export class Renderer extends Behaviour implements IRenderer {
542
544
  // handle reflection probe
543
545
  this._reflectionProbe = null;
544
546
  if (this.reflectionProbeUsage !== ReflectionProbeUsage.Off) {
545
- // if(this.gameObject.name.includes("Tank_Case_Jewlery") === false) return;
547
+ if(!this.probeAnchor) return;
546
548
  const obj = this.probeAnchor || this.gameObject;
547
549
  const isAnchor = this.probeAnchor ? true : false;
548
550
  this._reflectionProbe = ReflectionProbe.get(obj, this.context, isAnchor);
@@ -54,6 +54,7 @@ export { Gradient } from "../ParticleSystemModules";
54
54
  export { MinMaxCurve } from "../ParticleSystemModules";
55
55
  export { MinMaxGradient } from "../ParticleSystemModules";
56
56
  export { MainModule } from "../ParticleSystemModules";
57
+ export { ParticleBurst } from "../ParticleSystemModules";
57
58
  export { EmissionModule } from "../ParticleSystemModules";
58
59
  export { ColorOverLifetimeModule } from "../ParticleSystemModules";
59
60
  export { SizeOverLifetimeModule } from "../ParticleSystemModules";