@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.
- package/CHANGELOG.md +11 -0
- package/dist/needle-engine.d.ts +100 -40
- package/dist/needle-engine.js +367 -367
- package/dist/needle-engine.js.map +3 -3
- package/dist/needle-engine.min.js +37 -37
- package/dist/needle-engine.min.js.map +3 -3
- package/lib/engine/engine_element.js +1 -1
- package/lib/engine/engine_element.js.map +1 -1
- package/lib/engine/engine_element_loading.js +6 -1
- package/lib/engine/engine_element_loading.js.map +1 -1
- package/lib/engine/engine_gizmos.d.ts +8 -22
- package/lib/engine/engine_gizmos.js +37 -3
- package/lib/engine/engine_gizmos.js.map +1 -1
- package/lib/engine/engine_setup.d.ts +3 -0
- package/lib/engine/engine_setup.js +15 -0
- package/lib/engine/engine_setup.js.map +1 -1
- package/lib/engine/engine_three_utils.d.ts +16 -1
- package/lib/engine/engine_three_utils.js +94 -54
- package/lib/engine/engine_three_utils.js.map +1 -1
- package/lib/engine/engine_types.d.ts +6 -0
- package/lib/engine/engine_types.js.map +1 -1
- package/lib/engine-components/AnimationCurve.js +2 -2
- package/lib/engine-components/AnimationCurve.js.map +1 -1
- package/lib/engine-components/BoxHelperComponent.js +9 -10
- package/lib/engine-components/BoxHelperComponent.js.map +1 -1
- package/lib/engine-components/ParticleSystem.d.ts +24 -10
- package/lib/engine-components/ParticleSystem.js +136 -41
- package/lib/engine-components/ParticleSystem.js.map +1 -1
- package/lib/engine-components/ParticleSystemModules.d.ts +40 -6
- package/lib/engine-components/ParticleSystemModules.js +103 -21
- package/lib/engine-components/ParticleSystemModules.js.map +1 -1
- package/lib/engine-components/ReflectionProbe.js +29 -11
- package/lib/engine-components/ReflectionProbe.js.map +1 -1
- package/lib/engine-components/Renderer.d.ts +1 -0
- package/lib/engine-components/Renderer.js +4 -2
- package/lib/engine-components/Renderer.js.map +1 -1
- package/lib/engine-components/codegen/components.d.ts +1 -0
- package/lib/engine-components/codegen/components.js +1 -0
- package/lib/engine-components/codegen/components.js.map +1 -1
- package/package.json +2 -2
- package/src/engine/codegen/register_types.js +4 -0
- package/src/engine/dist/engine_three_utils.js +279 -0
- package/src/engine/engine_element.ts +1 -1
- package/src/engine/engine_element_loading.ts +5 -1
- package/src/engine/engine_gizmos.ts +45 -8
- package/src/engine/engine_setup.ts +25 -2
- package/src/engine/engine_three_utils.ts +103 -62
- package/src/engine/engine_types.ts +8 -1
- package/src/engine-components/AnimationCurve.ts +2 -2
- package/src/engine-components/BoxHelperComponent.ts +12 -15
- package/src/engine-components/ParticleSystem.ts +151 -75
- package/src/engine-components/ParticleSystemModules.ts +127 -24
- package/src/engine-components/ReflectionProbe.ts +37 -13
- package/src/engine-components/Renderer.ts +4 -2
- 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,
|
|
190
|
-
return
|
|
208
|
+
this.gradient.evaluate(t01, MinMaxGradient._temp);
|
|
209
|
+
return MinMaxGradient._temp
|
|
191
210
|
case ParticleSystemGradientMode.TwoColors:
|
|
192
|
-
return
|
|
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
|
-
|
|
196
|
-
|
|
197
|
-
return
|
|
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
|
-
|
|
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
|
-
|
|
279
|
-
|
|
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
|
-
|
|
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
|
-
|
|
391
|
+
let amount = Math.floor(this._summed);
|
|
302
392
|
this._summed -= amount;
|
|
303
|
-
|
|
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):
|
|
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 *=
|
|
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<{
|
|
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
|
|
113
|
-
if (!
|
|
114
|
-
if (
|
|
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
|
-
|
|
123
|
-
|
|
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.
|
|
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
|
-
|
|
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";
|