@needle-tools/engine 2.54.2-pre → 2.55.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 (72) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/needle-engine.d.ts +27 -4
  3. package/dist/needle-engine.js +352 -352
  4. package/dist/needle-engine.js.map +3 -3
  5. package/dist/needle-engine.min.js +38 -38
  6. package/dist/needle-engine.min.js.map +3 -3
  7. package/dist/needle-engine.tsbuildinfo +1 -1
  8. package/lib/engine/engine_lightdata.js +1 -1
  9. package/lib/engine/engine_lightdata.js.map +1 -1
  10. package/lib/engine/engine_mainloop_utils.js +8 -0
  11. package/lib/engine/engine_mainloop_utils.js.map +1 -1
  12. package/lib/engine/engine_physics.d.ts +1 -1
  13. package/lib/engine/engine_physics.js +44 -3
  14. package/lib/engine/engine_physics.js.map +1 -1
  15. package/lib/engine/engine_physics.types.d.ts +13 -0
  16. package/lib/engine/engine_physics.types.js +7 -0
  17. package/lib/engine/engine_physics.types.js.map +1 -1
  18. package/lib/engine/engine_setup.js +2 -2
  19. package/lib/engine/engine_setup.js.map +1 -1
  20. package/lib/engine/engine_time.d.ts +1 -0
  21. package/lib/engine/engine_time.js +7 -0
  22. package/lib/engine/engine_time.js.map +1 -1
  23. package/lib/engine/engine_types.d.ts +4 -1
  24. package/lib/engine/engine_types.js.map +1 -1
  25. package/lib/engine/engine_utils.d.ts +1 -0
  26. package/lib/engine/engine_utils.js +3 -0
  27. package/lib/engine/engine_utils.js.map +1 -1
  28. package/lib/engine-components/Collider.d.ts +2 -0
  29. package/lib/engine-components/Collider.js +4 -0
  30. package/lib/engine-components/Collider.js.map +1 -1
  31. package/lib/engine-components/ParticleSystem.d.ts +1 -0
  32. package/lib/engine-components/ParticleSystem.js +10 -5
  33. package/lib/engine-components/ParticleSystem.js.map +1 -1
  34. package/lib/engine-components/ParticleSystemModules.d.ts +1 -1
  35. package/lib/engine-components/ParticleSystemModules.js +25 -19
  36. package/lib/engine-components/ParticleSystemModules.js.map +1 -1
  37. package/lib/engine-components/Renderer.d.ts +1 -0
  38. package/lib/engine-components/Renderer.js +5 -0
  39. package/lib/engine-components/Renderer.js.map +1 -1
  40. package/lib/engine-components/RigidBody.js +1 -19
  41. package/lib/engine-components/RigidBody.js.map +1 -1
  42. package/lib/engine-components/SyncedTransform.js +1 -3
  43. package/lib/engine-components/SyncedTransform.js.map +1 -1
  44. package/lib/engine-components/VideoPlayer.d.ts +2 -1
  45. package/lib/engine-components/VideoPlayer.js +54 -51
  46. package/lib/engine-components/VideoPlayer.js.map +1 -1
  47. package/lib/engine-components/WebARSessionRoot.js +5 -0
  48. package/lib/engine-components/WebARSessionRoot.js.map +1 -1
  49. package/lib/engine-components/WebXR.js +13 -13
  50. package/lib/engine-components/WebXR.js.map +1 -1
  51. package/lib/engine-components/WebXRController.js +1 -2
  52. package/lib/engine-components/WebXRController.js.map +1 -1
  53. package/lib/tsconfig.tsbuildinfo +1 -1
  54. package/package.json +1 -1
  55. package/src/engine/engine_lightdata.ts +1 -1
  56. package/src/engine/engine_mainloop_utils.ts +6 -0
  57. package/src/engine/engine_physics.ts +47 -5
  58. package/src/engine/engine_physics.types.ts +17 -0
  59. package/src/engine/engine_setup.ts +2 -2
  60. package/src/engine/engine_time.ts +7 -1
  61. package/src/engine/engine_types.ts +5 -2
  62. package/src/engine/engine_utils.ts +4 -0
  63. package/src/engine-components/Collider.ts +3 -0
  64. package/src/engine-components/ParticleSystem.ts +10 -5
  65. package/src/engine-components/ParticleSystemModules.ts +27 -20
  66. package/src/engine-components/Renderer.ts +6 -0
  67. package/src/engine-components/RigidBody.ts +1 -20
  68. package/src/engine-components/SyncedTransform.ts +1 -3
  69. package/src/engine-components/VideoPlayer.ts +55 -51
  70. package/src/engine-components/WebARSessionRoot.ts +5 -0
  71. package/src/engine-components/WebXR.ts +15 -13
  72. package/src/engine-components/WebXRController.ts +1 -2
@@ -73,37 +73,37 @@ export class VideoPlayer extends Behaviour {
73
73
  private _playbackSpeed: number = 1;
74
74
  @serializable()
75
75
  get playbackSpeed(): number {
76
- return this.videoElement?.playbackRate ?? this._playbackSpeed;
76
+ return this._videoElement?.playbackRate ?? this._playbackSpeed;
77
77
  }
78
78
  set playbackSpeed(val: number) {
79
79
  this._playbackSpeed = val;
80
- if (this.videoElement)
81
- this.videoElement.playbackRate = val;
80
+ if (this._videoElement)
81
+ this._videoElement.playbackRate = val;
82
82
  }
83
83
 
84
84
  private _isLooping: boolean = false;
85
85
  get isLooping(): boolean {
86
- return this.videoElement?.loop ?? this._isLooping;
86
+ return this._videoElement?.loop ?? this._isLooping;
87
87
  }
88
88
  @serializable()
89
89
  set isLooping(val: boolean) {
90
90
  this._isLooping = val;
91
- if (this.videoElement)
92
- this.videoElement.loop = val;
91
+ if (this._videoElement)
92
+ this._videoElement.loop = val;
93
93
  }
94
94
 
95
95
  get currentTime(): number {
96
- return this.videoElement?.currentTime ?? this.time;
96
+ return this._videoElement?.currentTime ?? this.time;
97
97
  }
98
98
  set currentTime(val: number) {
99
- if (this.videoElement) {
100
- this.videoElement.currentTime = val;
99
+ if (this._videoElement) {
100
+ this._videoElement.currentTime = val;
101
101
  }
102
102
  else this.time = val;
103
103
  }
104
104
 
105
105
  get isPlaying(): boolean {
106
- const video = this.videoElement;
106
+ const video = this._videoElement;
107
107
  if (video) {
108
108
  return video.currentTime > 0 && !video.paused && !video.ended
109
109
  && video.readyState > video.HAVE_CURRENT_DATA;
@@ -112,13 +112,13 @@ export class VideoPlayer extends Behaviour {
112
112
  }
113
113
 
114
114
  get crossOrigin(): string | null {
115
- return this.videoElement?.crossOrigin ?? this._crossOrigin;
115
+ return this._videoElement?.crossOrigin ?? this._crossOrigin;
116
116
  }
117
117
  set crossOrigin(val: string | null) {
118
118
  this._crossOrigin = val;
119
- if (this.videoElement) {
120
- if (val !== null) this.videoElement.setAttribute("crossorigin", val);
121
- else this.videoElement.removeAttribute("crossorigin");
119
+ if (this._videoElement) {
120
+ if (val !== null) this._videoElement.setAttribute("crossorigin", val);
121
+ else this._videoElement.removeAttribute("crossorigin");
122
122
  }
123
123
  }
124
124
 
@@ -126,6 +126,10 @@ export class VideoPlayer extends Behaviour {
126
126
  return this._videoTexture;
127
127
  }
128
128
 
129
+ get videoElement() {
130
+ return this._videoElement;
131
+ }
132
+
129
133
  private _crossOrigin: string | null = "anonymous";
130
134
 
131
135
  private audioOutputMode: VideoAudioOutputMode = VideoAudioOutputMode.AudioSource;
@@ -134,7 +138,7 @@ export class VideoPlayer extends Behaviour {
134
138
  private clip?: string | MediaStream | null = null;
135
139
  private url?: string | null = null;
136
140
 
137
- private videoElement: HTMLVideoElement | null = null;
141
+ private _videoElement: HTMLVideoElement | null = null;
138
142
  private _videoTexture: THREE.VideoTexture | null = null;
139
143
  private videoMaterial: Material | null = null;
140
144
 
@@ -144,12 +148,12 @@ export class VideoPlayer extends Behaviour {
144
148
  setVideo(video: MediaStream) {
145
149
  this.clip = video;
146
150
  this.source = VideoSource.VideoClip;
147
- if (!this.videoElement) this.create(true);
151
+ if (!this._videoElement) this.create(true);
148
152
  else {
149
153
  // TODO: how to prevent interruption error when another video is already playing
150
- this.videoElement.srcObject = video;
154
+ this._videoElement.srcObject = video;
151
155
  if (this._isPlaying)
152
- this.videoElement.play();
156
+ this._videoElement.play();
153
157
  this.updateAspect();
154
158
  }
155
159
  }
@@ -160,9 +164,9 @@ export class VideoPlayer extends Behaviour {
160
164
  this.url = url;
161
165
  this.source = VideoSource.Url;
162
166
  if (debug) console.log("set url", url);
163
- if (!this.videoElement) this.create(true);
167
+ if (!this._videoElement) this.create(true);
164
168
  else {
165
- this.videoElement.src = url;
169
+ this._videoElement.src = url;
166
170
  if (this._isPlaying) {
167
171
  this.stop();
168
172
  this.play();
@@ -201,9 +205,9 @@ export class VideoPlayer extends Behaviour {
201
205
  }
202
206
 
203
207
  onDestroy(): void {
204
- if (this.videoElement) {
205
- this.videoElement.parentElement?.removeChild(this.videoElement);
206
- this.videoElement = null;
208
+ if (this._videoElement) {
209
+ this._videoElement.parentElement?.removeChild(this._videoElement);
210
+ this._videoElement = null;
207
211
  }
208
212
  if (this._videoTexture) {
209
213
  this._videoTexture.dispose();
@@ -231,27 +235,27 @@ export class VideoPlayer extends Behaviour {
231
235
  }
232
236
 
233
237
  play() {
234
- if (!this.videoElement) return;
235
- if (this._isPlaying && !this.videoElement?.ended && !this.videoElement?.paused) return;
238
+ if (!this._videoElement) return;
239
+ if (this._isPlaying && !this._videoElement?.ended && !this._videoElement?.paused) return;
236
240
  this._isPlaying = true;
237
- if (!this._receivedInput) this.videoElement.muted = true;
241
+ if (!this._receivedInput) this._videoElement.muted = true;
238
242
  this.updateVideoElementSettings();
239
- this.videoElement?.play().catch(err => {
243
+ this._videoElement?.play().catch(err => {
240
244
  console.warn(err);
241
245
  });
242
- if (debug) console.log("play", this.videoElement);
246
+ if (debug) console.log("play", this._videoElement);
243
247
  }
244
248
 
245
249
  stop() {
246
250
  this._isPlaying = false;
247
- if (!this.videoElement) return;
248
- this.videoElement.currentTime = 0;
249
- this.videoElement.pause();
251
+ if (!this._videoElement) return;
252
+ this._videoElement.currentTime = 0;
253
+ this._videoElement.pause();
250
254
  }
251
255
 
252
256
  pause(): void {
253
257
  this._isPlaying = false;
254
- this.videoElement?.pause();
258
+ this._videoElement?.pause();
255
259
  }
256
260
 
257
261
 
@@ -270,23 +274,23 @@ export class VideoPlayer extends Behaviour {
270
274
 
271
275
  // console.log(src, this);
272
276
 
273
- if (!this.videoElement) {
274
- this.videoElement = this.createVideoElement();
275
- this.context.domElement?.prepend(this.videoElement);
277
+ if (!this._videoElement) {
278
+ this._videoElement = this.createVideoElement();
279
+ this.context.domElement?.prepend(this._videoElement);
276
280
  // hide it because otherwise it would overlay the website with default css
277
281
  this.updateVideoElementStyles();
278
282
  }
279
283
  if (typeof src === "string") {
280
- this.videoElement.src = src;
281
- const str = this.videoElement["captureStream"]?.call(this.videoElement);
284
+ this._videoElement.src = src;
285
+ const str = this._videoElement["captureStream"]?.call(this._videoElement);
282
286
  this.clip = str;
283
287
  }
284
288
  else
285
- this.videoElement.srcObject = src;
289
+ this._videoElement.srcObject = src;
286
290
 
287
291
 
288
292
  if (!this._videoTexture)
289
- this._videoTexture = new THREE.VideoTexture(this.videoElement);
293
+ this._videoTexture = new THREE.VideoTexture(this._videoElement);
290
294
  this._videoTexture.flipY = false;
291
295
  this._videoTexture.encoding = THREE.sRGBEncoding;
292
296
  this.handleBeginPlaying(playAutomatically);
@@ -327,7 +331,7 @@ export class VideoPlayer extends Behaviour {
327
331
 
328
332
  private handleBeginPlaying(playAutomatically: boolean) {
329
333
  if (!this.enabled) return;
330
- if (!this.videoElement) return;
334
+ if (!this._videoElement) return;
331
335
 
332
336
  this._targetObjects.length = 0;
333
337
 
@@ -385,24 +389,24 @@ export class VideoPlayer extends Behaviour {
385
389
  }
386
390
 
387
391
  private updateVideoElementSettings() {
388
- if (!this.videoElement) return;
389
- this.videoElement.loop = this._isLooping;
390
- this.videoElement.currentTime = this.currentTime;
391
- this.videoElement.playbackRate = this._playbackSpeed;
392
+ if (!this._videoElement) return;
393
+ this._videoElement.loop = this._isLooping;
394
+ this._videoElement.currentTime = this.currentTime;
395
+ this._videoElement.playbackRate = this._playbackSpeed;
392
396
  // dont open in fullscreen on ios
393
- this.videoElement.playsInline = true;
394
- this.videoElement.muted = !this._receivedInput && this.audioOutputMode !== VideoAudioOutputMode.None;
397
+ this._videoElement.playsInline = true;
398
+ this._videoElement.muted = !this._receivedInput && this.audioOutputMode !== VideoAudioOutputMode.None;
395
399
  if (this.playOnAwake || this.playOnEnable)
396
- this.videoElement.autoplay = true;
400
+ this._videoElement.autoplay = true;
397
401
  }
398
402
 
399
403
  private updateVideoElementStyles() {
400
- if (!this.videoElement) return;
404
+ if (!this._videoElement) return;
401
405
  // set style here so preview frame is rendered
402
406
  // set display and selectable because otherwise is interfers with input/focus e.g. breaks orbit control
403
- this.videoElement.style.userSelect = "none";
404
- this.videoElement.style.visibility = "hidden";
405
- this.videoElement.style.display = "none";
407
+ this._videoElement.style.userSelect = "none";
408
+ this._videoElement.style.visibility = "hidden";
409
+ this._videoElement.style.display = "none";
406
410
  this.updateAspect();
407
411
  }
408
412
 
@@ -92,6 +92,9 @@ export class WebARSessionRoot extends Behaviour {
92
92
  placeAt(rig: Object3D | null, mat: Matrix4) {
93
93
  if (!this._placementPose) this._placementPose = new Matrix4();
94
94
  this._placementPose.copy(mat);
95
+ // apply session root offset
96
+ const invertedSessionRoot = this.gameObject.matrixWorld.clone().invert();
97
+ this._placementPose.premultiply(invertedSessionRoot);
95
98
  if (rig) {
96
99
 
97
100
  if (this.invertForward) {
@@ -146,9 +149,11 @@ export class WebARSessionRoot extends Behaviour {
146
149
  if (!rig || !this._placementPose) {
147
150
  return;
148
151
  }
152
+ // Capture the rig position before the first time we move it during a session
149
153
  if (!this._rigStartPose) {
150
154
  this._rigStartPose = rig.matrix.clone();
151
155
  }
156
+ // we apply the transform to the rig because we want to move the user's position for easy networking
152
157
  rig.matrixAutoUpdate = false;
153
158
  rig.matrix.multiplyMatrices(new Matrix4().makeScale(scale, scale, scale), this._placementPose);
154
159
  rig.matrix.decompose(rig.position, rig.quaternion, rig.scale);
@@ -143,6 +143,7 @@ export class WebXR extends Behaviour {
143
143
  return this.rig;
144
144
  }
145
145
 
146
+
146
147
  private controllers: WebXRController[] = [];
147
148
  public get Controllers(): WebXRController[] {
148
149
  return this.controllers;
@@ -249,17 +250,21 @@ export class WebXR extends Behaviour {
249
250
  // TODO: figure out why screen is black if we enable the code written here
250
251
  // const referenceSpace = renderer.xr.getReferenceSpace();
251
252
  const session = this.context.renderer.xr.getSession();
253
+
252
254
 
253
255
  if (session) {
254
256
  const pose = frame.getViewerPose(this.context.renderer.xr.getReferenceSpace());
257
+ if(!pose) return;
255
258
  this._currentHeadPose = pose;
256
- if (!pose) return; // e.g. if user is not wearing headset
257
259
  const transform: XRRigidTransform = pose?.transform;
258
-
259
260
  if (transform) {
260
261
  this._transformOrientation.set(transform.orientation.x, transform.orientation.y, transform.orientation.z, transform.orientation.w);
261
262
  }
262
263
 
264
+ if (WebXR._isInXr === false && session) {
265
+ this.onEnterXR(session, frame);
266
+ }
267
+
263
268
  for (const ctrl of this.controllers) {
264
269
  ctrl.onUpdate(session);
265
270
  }
@@ -269,9 +274,6 @@ export class WebXR extends Behaviour {
269
274
  }
270
275
  }
271
276
 
272
- if (WebXR._isInXr === false && session) {
273
- this.onEnterXR(session, frame);
274
- }
275
277
  WebXR.events.dispatchEvent({ type: WebXREvent.XRUpdate, frame: frame, xr: this.context.renderer.xr, rig: this.rig });
276
278
  }
277
279
 
@@ -329,7 +331,7 @@ export class WebXR extends Behaviour {
329
331
  if (xrRig) {
330
332
  // make it match unity forward
331
333
  this.rig = xrRig.gameObject;
332
- this.rig.rotateY(Math.PI);
334
+ // this.rig.rotateY(Math.PI);
333
335
  // this.rig.position.copy(existing.worldPosition);
334
336
  // this.rig.quaternion.premultiply(existing.worldQuaternion);
335
337
  }
@@ -577,7 +579,7 @@ export class WebAR {
577
579
  this.reticleParent.name = "AR Reticle Parent";
578
580
  this.reticleParent.matrixAutoUpdate = false;
579
581
  this.reticleParent.add(this.reticle);
580
- this.reticleParent.matrix.copy(this.sessionRoot.gameObject.matrixWorld);
582
+ // this.reticleParent.matrix.copy(this.sessionRoot.gameObject.matrixWorld);
581
583
 
582
584
  if (this.webxr.scene) {
583
585
  this.context.scene.add(this.reticleParent);
@@ -632,11 +634,11 @@ export class WebAR {
632
634
  this.didPlaceARSessionRoot = true;
633
635
  const rig = this.webxr.Rig;
634
636
  const placementMatrix = arPlacementWithoutHitTestMatrix.clone();
635
- if (rig) {
636
- const positionFromRig = new Vector3(0, 0, 0).add(rig.position).divideScalar(this.sessionRoot?.arScale ?? 1);
637
- placementMatrix.multiply(new Matrix4().makeTranslation(positionFromRig.x, positionFromRig.y, positionFromRig.z));
638
- // placementMatrix.setPosition(positionFromRig);
639
- }
637
+ // if (rig) {
638
+ // const positionFromRig = new Vector3(0, 0, 0).add(rig.position).divideScalar(this.sessionRoot?.arScale ?? 1);
639
+ // placementMatrix.multiply(new Matrix4().makeTranslation(positionFromRig.x, positionFromRig.y, positionFromRig.z));
640
+ // // placementMatrix.setPosition(positionFromRig);
641
+ // }
640
642
  this.sessionRoot?.placeAt(rig, placementMatrix);
641
643
  }
642
644
  return;
@@ -676,4 +678,4 @@ export class WebAR {
676
678
  }
677
679
  }
678
680
 
679
- const arPlacementWithoutHitTestMatrix = new Matrix4().identity().makeTranslation(0, -0.5, 0);
681
+ const arPlacementWithoutHitTestMatrix = new Matrix4().identity().makeTranslation(0, 0, 0);
@@ -381,7 +381,7 @@ export class WebXRController extends Behaviour {
381
381
  }
382
382
 
383
383
  if (this.raycastLine) {
384
- const allowRaycastLineVisible = this.showRaycastLine && this.context.isInVR;
384
+ const allowRaycastLineVisible = this.showRaycastLine && this.type !== ControllerType.Touch;
385
385
  if (this.type === ControllerType.Touch) {
386
386
  this.raycastLine.visible = false;
387
387
  }
@@ -1117,7 +1117,6 @@ export class AttachedObject {
1117
1117
  if (this.rigidbodies != null) {
1118
1118
  for (const rb of this.rigidbodies) {
1119
1119
  rb.wakeUp();
1120
- rb.setBodyFromGameObject({ x: 0, y: 0, z: 0 });
1121
1120
  }
1122
1121
  }
1123
1122