@needle-tools/engine 3.2.1-alpha → 3.2.3-alpha
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 +8 -0
- package/dist/needle-engine.js +3943 -3886
- package/dist/needle-engine.min.js +74 -74
- package/dist/needle-engine.umd.cjs +86 -86
- package/lib/engine/engine_input.js +9 -3
- package/lib/engine/engine_input.js.map +1 -1
- package/lib/engine/engine_rendererdata.d.ts +1 -1
- package/lib/engine/engine_rendererdata.js +3 -1
- package/lib/engine/engine_rendererdata.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_lighting_settings.js +1 -1
- package/lib/engine/extensions/NEEDLE_lighting_settings.js.map +1 -1
- package/lib/engine-components/ParticleSystem.js +2 -1
- package/lib/engine-components/ParticleSystem.js.map +1 -1
- package/lib/engine-components/ParticleSystemModules.d.ts +17 -2
- package/lib/engine-components/ParticleSystemModules.js +105 -14
- package/lib/engine-components/ParticleSystemModules.js.map +1 -1
- package/lib/engine-components/SceneSwitcher.d.ts +1 -1
- package/lib/engine-components/SceneSwitcher.js +9 -7
- package/lib/engine-components/SceneSwitcher.js.map +1 -1
- package/lib/engine-components/SpriteRenderer.js +3 -0
- package/lib/engine-components/SpriteRenderer.js.map +1 -1
- package/lib/engine-components/VideoPlayer.js +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/engine/codegen/register_types.js +2 -2
- package/src/engine/engine_input.ts +6 -3
- package/src/engine/engine_rendererdata.ts +2 -1
- package/src/engine/extensions/NEEDLE_lighting_settings.ts +1 -1
- package/src/engine-components/ParticleSystem.ts +2 -1
- package/src/engine-components/ParticleSystemModules.ts +98 -15
- package/src/engine-components/SceneSwitcher.ts +9 -7
- package/src/engine-components/SpriteRenderer.ts +4 -0
- package/src/engine-components/VideoPlayer.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@needle-tools/engine",
|
|
3
|
-
"version": "3.2.
|
|
3
|
+
"version": "3.2.3-alpha",
|
|
4
4
|
"description": "Needle Engine is a web-based runtime for 3D apps. It runs on your machine for development with great integrations into editors like Unity or Blender - and can be deployed onto any device! It is flexible, extensible and networking and XR are built-in",
|
|
5
5
|
"main": "dist/needle-engine.umd.cjs",
|
|
6
6
|
"type": "module",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TypeStore } from "./../engine_typestore"
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
// Import types
|
|
4
4
|
import { __Ignore } from "../../engine-components/codegen/components";
|
|
5
5
|
import { AlignmentConstraint } from "../../engine-components/AlignmentConstraint";
|
|
@@ -184,7 +184,7 @@ import { XRGrabModel } from "../../engine-components/WebXRGrabRendering";
|
|
|
184
184
|
import { XRGrabRendering } from "../../engine-components/WebXRGrabRendering";
|
|
185
185
|
import { XRRig } from "../../engine-components/WebXRRig";
|
|
186
186
|
import { XRState } from "../../engine-components/XRFlag";
|
|
187
|
-
|
|
187
|
+
|
|
188
188
|
// Register types
|
|
189
189
|
TypeStore.add("__Ignore", __Ignore);
|
|
190
190
|
TypeStore.add("AlignmentConstraint", AlignmentConstraint);
|
|
@@ -243,28 +243,31 @@ export class Input extends EventTarget {
|
|
|
243
243
|
return null;
|
|
244
244
|
}
|
|
245
245
|
isKeyDown(keyCode: KeyCode | string) {
|
|
246
|
+
if (!this.context.application.isVisible || !this.context.application.hasFocus) return false;
|
|
246
247
|
const codes = this.getCodeForCommonKeyName(keyCode);
|
|
247
248
|
if (codes !== null) {
|
|
248
249
|
for (const code of codes) if (this.isKeyDown(code)) return true;
|
|
249
250
|
return false;
|
|
250
251
|
}
|
|
251
|
-
return this.
|
|
252
|
+
return this.keysPressed[keyCode]?.startFrame === this.context.time.frameCount && this.keysPressed[keyCode].pressed;
|
|
252
253
|
}
|
|
253
254
|
isKeyUp(keyCode: KeyCode | string) {
|
|
255
|
+
if (!this.context.application.isVisible || !this.context.application.hasFocus) return false;
|
|
254
256
|
const codes = this.getCodeForCommonKeyName(keyCode);
|
|
255
257
|
if (codes !== null) {
|
|
256
258
|
for (const code of codes) if (this.isKeyUp(code)) return true;
|
|
257
259
|
return false;
|
|
258
260
|
}
|
|
259
|
-
return this.
|
|
261
|
+
return this.keysPressed[keyCode]?.frame === this.context.time.frameCount && !this.keysPressed[keyCode].pressed;
|
|
260
262
|
}
|
|
261
263
|
isKeyPressed(keyCode: KeyCode | string) {
|
|
264
|
+
if (!this.context.application.isVisible || !this.context.application.hasFocus) return false;
|
|
262
265
|
const codes = this.getCodeForCommonKeyName(keyCode);
|
|
263
266
|
if (codes !== null) {
|
|
264
267
|
for (const code of codes) if (this.isKeyPressed(code)) return true;
|
|
265
268
|
return false;
|
|
266
269
|
}
|
|
267
|
-
return this.
|
|
270
|
+
return this.keysPressed[keyCode]?.pressed;// && time.frameCount - this.keysPressed[keyCode].frame < 100;
|
|
268
271
|
}
|
|
269
272
|
|
|
270
273
|
// utility helper for mapping common names to actual codes; e.g. "Shift" -> "ShiftLeft" and "ShiftRight" or "a" -> "KeyA"
|
|
@@ -136,7 +136,8 @@ export class RendererData {
|
|
|
136
136
|
}
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
-
disableReflection() {
|
|
139
|
+
disableReflection(sourceId? : SourceIdentifier) {
|
|
140
|
+
if(sourceId && sourceId !== this._currentReflectionId) return;
|
|
140
141
|
const scene = this.context.scene;
|
|
141
142
|
scene.environment = null;
|
|
142
143
|
}
|
|
@@ -160,6 +160,6 @@ export class SceneLightSettings extends Behaviour {
|
|
|
160
160
|
if (this._lightProbeObj) this._lightProbeObj.removeFromParent();
|
|
161
161
|
if(this._ambientLightObj) this._ambientLightObj.removeFromParent();
|
|
162
162
|
if (this.sourceId)
|
|
163
|
-
this.context.rendererData.disableReflection();
|
|
163
|
+
this.context.rendererData.disableReflection(this.sourceId);
|
|
164
164
|
}
|
|
165
165
|
}
|
|
@@ -414,6 +414,7 @@ class VelocityBehaviour extends ParticleSystemBaseBehaviour {
|
|
|
414
414
|
particle[$gravitySpeed] = 1;
|
|
415
415
|
|
|
416
416
|
particle[$velocityLerpFactor] = Math.random();
|
|
417
|
+
this.system.velocityOverLifetime?.init(particle);
|
|
417
418
|
|
|
418
419
|
this._gravityDirection.set(0, -1, 0);
|
|
419
420
|
if (this.system.main.simulationSpace === ParticleSystemSimulationSpace.Local)
|
|
@@ -463,7 +464,7 @@ class VelocityBehaviour extends ParticleSystemBaseBehaviour {
|
|
|
463
464
|
// limit or modify speed
|
|
464
465
|
const velocity = this.system.velocityOverLifetime;
|
|
465
466
|
if (velocity.enabled) {
|
|
466
|
-
velocity.apply(0, particle.position, particle.velocity, delta, particle.age, particle.life);
|
|
467
|
+
velocity.apply(particle, 0, particle.position, particle.velocity, delta, particle.age, particle.life);
|
|
467
468
|
}
|
|
468
469
|
|
|
469
470
|
const limitVelocityOverLifetime = this.system.limitVelocityOverLifetime;
|
|
@@ -567,12 +567,24 @@ export class ShapeModule implements EmitterShape {
|
|
|
567
567
|
}
|
|
568
568
|
}
|
|
569
569
|
|
|
570
|
-
private
|
|
570
|
+
private applyRotation(vector: Vector3) {
|
|
571
571
|
const isRotated = this.rotation.x !== 0 || this.rotation.y !== 0 || this.rotation.z !== 0;
|
|
572
572
|
if (isRotated) {
|
|
573
|
+
// console.log(this._rotation);
|
|
574
|
+
// TODO: we need to convert this to threejs euler
|
|
573
575
|
this._rotation.x = Mathf.toRadians(this.rotation.x);
|
|
574
|
-
this._rotation.y =
|
|
575
|
-
this._rotation.z =
|
|
576
|
+
this._rotation.y = Mathf.toRadians(this.rotation.y);
|
|
577
|
+
this._rotation.z = Mathf.toRadians(this.rotation.z);
|
|
578
|
+
this._rotation.order = 'ZYX';
|
|
579
|
+
vector.applyEuler(this._rotation);
|
|
580
|
+
// this._quat.setFromEuler(this._rotation);
|
|
581
|
+
// // this._quat.invert();
|
|
582
|
+
// this._quat.x *= -1;
|
|
583
|
+
// // this._quat.y *= -1;
|
|
584
|
+
// // this._quat.z *= -1;
|
|
585
|
+
// this._quat.w *= -1;
|
|
586
|
+
// vector.applyQuaternion(this._quat);
|
|
587
|
+
|
|
576
588
|
}
|
|
577
589
|
return isRotated;
|
|
578
590
|
}
|
|
@@ -624,8 +636,7 @@ export class ShapeModule implements EmitterShape {
|
|
|
624
636
|
this.randomizePosition(this._vector, this.randomPositionAmount);
|
|
625
637
|
}
|
|
626
638
|
|
|
627
|
-
|
|
628
|
-
this._vector.applyEuler(this._rotation);
|
|
639
|
+
this.applyRotation(this._vector);
|
|
629
640
|
|
|
630
641
|
if (isWorldSpace) {
|
|
631
642
|
this._vector.applyQuaternion(this.system.worldQuaternion);
|
|
@@ -663,6 +674,8 @@ export class ShapeModule implements EmitterShape {
|
|
|
663
674
|
this._dir.set(rx, ry, rz)
|
|
664
675
|
if (this.system?.worldspace)
|
|
665
676
|
this._dir.sub(this.system.worldPos)
|
|
677
|
+
else
|
|
678
|
+
this._dir.sub(this.position)
|
|
666
679
|
break;
|
|
667
680
|
default:
|
|
668
681
|
this._dir.set(0, 0, 1);
|
|
@@ -671,8 +684,7 @@ export class ShapeModule implements EmitterShape {
|
|
|
671
684
|
if (this._space === ParticleSystemSimulationSpace.World) {
|
|
672
685
|
this._dir.applyQuaternion(this.system.worldQuaternion);
|
|
673
686
|
}
|
|
674
|
-
|
|
675
|
-
this._dir.applyEuler(this._rotation);
|
|
687
|
+
this.applyRotation(this._dir);
|
|
676
688
|
this._dir.normalize();
|
|
677
689
|
this.spherizeDirection(this._dir, this.sphericalDirectionAmount);
|
|
678
690
|
this.randomizeDirection(this._dir, this.randomDirectionAmount);
|
|
@@ -982,11 +994,29 @@ export class VelocityOverLifetimeModule {
|
|
|
982
994
|
@serializable()
|
|
983
995
|
enabled!: boolean;
|
|
984
996
|
|
|
985
|
-
|
|
997
|
+
@serializable()
|
|
998
|
+
space: ParticleSystemSimulationSpace = ParticleSystemSimulationSpace.Local;
|
|
986
999
|
|
|
1000
|
+
@serializable(MinMaxCurve)
|
|
1001
|
+
orbitalX!: MinMaxCurve;
|
|
1002
|
+
@serializable(MinMaxCurve)
|
|
1003
|
+
orbitalY!: MinMaxCurve;
|
|
1004
|
+
@serializable(MinMaxCurve)
|
|
1005
|
+
orbitalZ!: MinMaxCurve;
|
|
987
1006
|
|
|
988
1007
|
@serializable()
|
|
989
|
-
|
|
1008
|
+
orbitalXMultiplier!: number;
|
|
1009
|
+
@serializable()
|
|
1010
|
+
orbitalYMultiplier!: number;
|
|
1011
|
+
@serializable()
|
|
1012
|
+
orbitalZMultiplier!: number;
|
|
1013
|
+
|
|
1014
|
+
@serializable()
|
|
1015
|
+
orbitalOffsetX!: number;
|
|
1016
|
+
@serializable()
|
|
1017
|
+
orbitalOffsetY!: number;
|
|
1018
|
+
@serializable()
|
|
1019
|
+
orbitalOffsetZ!: number;
|
|
990
1020
|
|
|
991
1021
|
@serializable(MinMaxCurve)
|
|
992
1022
|
speedModifier!: MinMaxCurve;
|
|
@@ -1013,8 +1043,23 @@ export class VelocityOverLifetimeModule {
|
|
|
1013
1043
|
}
|
|
1014
1044
|
|
|
1015
1045
|
private _temp: Vector3 = new Vector3();
|
|
1046
|
+
private _temp2: Vector3 = new Vector3();
|
|
1047
|
+
private _temp3: Vector3 = new Vector3();
|
|
1048
|
+
private _hasOrbital = false;
|
|
1049
|
+
private _index = 0;
|
|
1050
|
+
private _orbitalMatrix: Matrix4 = new Matrix4();
|
|
1051
|
+
|
|
1052
|
+
init(particle: object) {
|
|
1053
|
+
if (this._index == 0) particle["debug"] = true;
|
|
1054
|
+
this._index += 1;
|
|
1055
|
+
particle["orbitx"] = this.orbitalX.evaluate(Math.random());
|
|
1056
|
+
particle["orbity"] = this.orbitalY.evaluate(Math.random());
|
|
1057
|
+
particle["orbitz"] = this.orbitalZ.evaluate(Math.random());
|
|
1058
|
+
// console.log(particle["orbitx"], particle["orbity"], particle["orbitz"])
|
|
1059
|
+
this._hasOrbital = particle["orbitx"] != 0 || particle["orbity"] != 0 || particle["orbitz"] != 0;
|
|
1060
|
+
}
|
|
1016
1061
|
|
|
1017
|
-
apply(_index: number, _pos: Vec3, vel: Vec3, _dt: number, age: number, life: number) {
|
|
1062
|
+
apply(_particle: object, _index: number, _pos: Vec3, vel: Vec3, _dt: number, age: number, life: number) {
|
|
1018
1063
|
if (!this.enabled) return;
|
|
1019
1064
|
const t = age / life;
|
|
1020
1065
|
|
|
@@ -1024,13 +1069,51 @@ export class VelocityOverLifetimeModule {
|
|
|
1024
1069
|
const z = this.z.evaluate(t);
|
|
1025
1070
|
this._temp.set(-x, y, z);
|
|
1026
1071
|
if (this._system) {
|
|
1027
|
-
if (this.space === ParticleSystemSimulationSpace.World) {
|
|
1028
|
-
|
|
1029
|
-
}
|
|
1030
|
-
if (this._system.main.simulationSpace === ParticleSystemSimulationSpace.World) {
|
|
1031
|
-
|
|
1072
|
+
// if (this.space === ParticleSystemSimulationSpace.World) {
|
|
1073
|
+
// this._temp.applyQuaternion(this._system.worldQuaternionInverted);
|
|
1074
|
+
// }
|
|
1075
|
+
// if (this._system.main.simulationSpace === ParticleSystemSimulationSpace.World) {
|
|
1076
|
+
// this._temp.applyQuaternion(this._system.worldQuaternion);
|
|
1077
|
+
// }
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
if (this._hasOrbital) {
|
|
1081
|
+
const position = this._system?.worldPos;
|
|
1082
|
+
if (position) {
|
|
1083
|
+
|
|
1084
|
+
// TODO: we absolutely need to fix this, this is a hack for a specific usecase and doesnt work yet correctly
|
|
1085
|
+
// https://github.com/needle-tools/needle-tiny/issues/710
|
|
1086
|
+
|
|
1087
|
+
const pos = this._temp2.set(_pos.x, _pos.y, _pos.z);
|
|
1088
|
+
|
|
1089
|
+
const ox = this.orbitalXMultiplier;// particle["orbitx"];
|
|
1090
|
+
const oy = this.orbitalYMultiplier;// particle["orbity"];
|
|
1091
|
+
const oz = this.orbitalZMultiplier;// particle["orbitz"];
|
|
1092
|
+
const angle = speed * Math.PI * 2 * 10; // < Oh god
|
|
1093
|
+
|
|
1094
|
+
const cosX = Math.cos(angle * ox);
|
|
1095
|
+
const sinX = Math.sin(angle * ox);
|
|
1096
|
+
const cosY = Math.cos(angle * oy);
|
|
1097
|
+
const sinY = Math.sin(angle * oy);
|
|
1098
|
+
const cosZ = Math.cos(angle * oz);
|
|
1099
|
+
const sinZ = Math.sin(angle * oz);
|
|
1100
|
+
|
|
1101
|
+
const newX = pos.x * (cosY * cosZ) + pos.y * (cosY * sinZ) + pos.z * (-sinY);
|
|
1102
|
+
const newY = pos.x * (sinX * sinY * cosZ - cosX * sinZ) + pos.y * (sinX * sinY * sinZ + cosX * cosZ) + pos.z * (sinX * cosY);
|
|
1103
|
+
const newZ = pos.x * (cosX * sinY * cosZ + sinX * sinZ) + pos.y * (cosX * sinY * sinZ - sinX * cosZ) + pos.z * (cosX * cosY);
|
|
1104
|
+
|
|
1105
|
+
// pos.x += this.orbitalOffsetX;
|
|
1106
|
+
// pos.y += this.orbitalOffsetY;
|
|
1107
|
+
// pos.z += this.orbitalOffsetZ;
|
|
1108
|
+
const v = this._temp3.set(pos.x - newX, pos.y - newY, pos.z - newZ);
|
|
1109
|
+
v.normalize();
|
|
1110
|
+
v.multiplyScalar(.2 / _dt * (Math.max(this.orbitalXMultiplier, this.orbitalYMultiplier, this.orbitalZMultiplier)));
|
|
1111
|
+
vel.x += v.x;
|
|
1112
|
+
vel.y += v.y;
|
|
1113
|
+
vel.z += v.z;
|
|
1032
1114
|
}
|
|
1033
1115
|
}
|
|
1116
|
+
|
|
1034
1117
|
vel.x += this._temp.x;
|
|
1035
1118
|
vel.y += this._temp.y;
|
|
1036
1119
|
vel.z += this._temp.z;
|
|
@@ -47,14 +47,16 @@ export class SceneSwitcher extends Behaviour {
|
|
|
47
47
|
private _currentScene: AssetReference | undefined = undefined;
|
|
48
48
|
private _engineElementOverserver: MutationObserver | undefined = undefined;
|
|
49
49
|
|
|
50
|
-
start() {
|
|
51
|
-
if (!this.tryLoadFromQueryParam()) {
|
|
50
|
+
async start() {
|
|
51
|
+
if (this._currentIndex === -1 && !await this.tryLoadFromQueryParam()) {
|
|
52
52
|
const value = this.context.domElement.getAttribute(ENGINE_ELEMENT_SCENE_ATTRIBUTE_NAME);
|
|
53
53
|
// let locked = this.lock;
|
|
54
54
|
try {
|
|
55
55
|
// this.lock = false;
|
|
56
|
-
if (value === null || !this.trySelectSceneFromValue(value))
|
|
57
|
-
this.
|
|
56
|
+
if (value === null || !await this.trySelectSceneFromValue(value)) {
|
|
57
|
+
if (this._currentIndex === -1)
|
|
58
|
+
this.select(0);
|
|
59
|
+
}
|
|
58
60
|
}
|
|
59
61
|
finally {
|
|
60
62
|
// this.lock = locked;
|
|
@@ -202,10 +204,10 @@ export class SceneSwitcher extends Behaviour {
|
|
|
202
204
|
}
|
|
203
205
|
|
|
204
206
|
private tryLoadFromQueryParam() {
|
|
205
|
-
if (!this.queryParameterName?.length) return
|
|
207
|
+
if (!this.queryParameterName?.length) return couldNotLoadScenePromise;
|
|
206
208
|
// try restore the scene from the url
|
|
207
209
|
const value = getParam(this.queryParameterName);
|
|
208
|
-
if (typeof value === "boolean") return
|
|
210
|
+
if (typeof value === "boolean") return couldNotLoadScenePromise;
|
|
209
211
|
return this.trySelectSceneFromValue(value);
|
|
210
212
|
}
|
|
211
213
|
|
|
@@ -233,7 +235,7 @@ export class SceneSwitcher extends Behaviour {
|
|
|
233
235
|
}
|
|
234
236
|
}
|
|
235
237
|
|
|
236
|
-
if (isLocalNetwork()) console.warn("
|
|
238
|
+
if (isLocalNetwork()) console.warn("Can not find scene: \"" + value + "\"", this)
|
|
237
239
|
|
|
238
240
|
return couldNotLoadScenePromise;
|
|
239
241
|
}
|
|
@@ -424,7 +424,7 @@ export class VideoPlayer extends Behaviour {
|
|
|
424
424
|
this._videoElement.playbackRate = this._playbackSpeed;
|
|
425
425
|
// dont open in fullscreen on ios
|
|
426
426
|
this._videoElement.playsInline = true;
|
|
427
|
-
let muted = !this._receivedInput
|
|
427
|
+
let muted = !this._receivedInput || this.audioOutputMode === VideoAudioOutputMode.None;
|
|
428
428
|
if (!muted && this._muted) muted = true;
|
|
429
429
|
this._videoElement.muted = muted;
|
|
430
430
|
if (this.playOnAwake)
|