@needle-tools/engine 4.5.8 → 4.6.0-next.74b55ae

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 +10 -0
  2. package/dist/{gltf-progressive-Bx_ZJgfQ.min.js → gltf-progressive-Bm9eEfgu.min.js} +1 -1
  3. package/dist/{gltf-progressive-Ccf3INjK.umd.cjs → gltf-progressive-Dn6o99rH.umd.cjs} +1 -1
  4. package/dist/{gltf-progressive-D8GP6sjZ.js → gltf-progressive-GjIqwSG3.js} +2 -2
  5. package/dist/{needle-engine.bundle-2--i65ba.umd.cjs → needle-engine.bundle-B28dL528.umd.cjs} +125 -125
  6. package/dist/{needle-engine.bundle-DsPSVnUc.min.js → needle-engine.bundle-DDJrVI3Z.min.js} +122 -122
  7. package/dist/{needle-engine.bundle-A-KGqR38.js → needle-engine.bundle-ZjqmTqX5.js} +3948 -3931
  8. package/dist/needle-engine.js +4 -4
  9. package/dist/needle-engine.min.js +1 -1
  10. package/dist/needle-engine.umd.cjs +1 -1
  11. package/dist/{postprocessing-CLwnKusi.umd.cjs → postprocessing-CRQa6Qxn.umd.cjs} +177 -97
  12. package/dist/{postprocessing-DS5I4Iim.js → postprocessing-D6W1EyZ-.js} +1095 -1001
  13. package/dist/{postprocessing-CdIScgB8.min.js → postprocessing-DF8AlRgW.min.js} +178 -98
  14. package/dist/{three-CFtLGNtV.min.js → three-Boa-jOq-.min.js} +18 -18
  15. package/dist/{three-1JG7vpNC.js → three-Bz6X1mrw.js} +0 -1
  16. package/dist/{three-f-JuZtOs.umd.cjs → three-DMrv-4ar.umd.cjs} +20 -20
  17. package/dist/{three-examples-BeoqFh8m.umd.cjs → three-examples-C7ryg8vN.umd.cjs} +1 -1
  18. package/dist/{three-examples-CPlN41GO.min.js → three-examples-DuVhxqft.min.js} +1 -1
  19. package/dist/{three-examples-CyWe9wwo.js → three-examples-GggCDHv0.js} +1 -1
  20. package/dist/{three-mesh-ui-B18kdQmk.js → three-mesh-ui-CLNOfsWn.js} +1 -1
  21. package/dist/{three-mesh-ui-BMeLuYD5.min.js → three-mesh-ui-CY6Izc7C.min.js} +1 -1
  22. package/dist/{three-mesh-ui-DMdtSVhY.umd.cjs → three-mesh-ui-CwlN0FUC.umd.cjs} +1 -1
  23. package/dist/{vendor-BbM-oI6p.js → vendor-BSD1RQIh.js} +1 -1
  24. package/dist/{vendor-CJFfVMoq.umd.cjs → vendor-DHr4aqIZ.umd.cjs} +1 -1
  25. package/dist/{vendor-CTtGKiDe.min.js → vendor-zxXa3Dmr.min.js} +1 -1
  26. package/lib/engine/engine_assetdatabase.js +3 -1
  27. package/lib/engine/engine_assetdatabase.js.map +1 -1
  28. package/lib/engine/engine_context.d.ts +2 -2
  29. package/lib/engine/engine_context.js +11 -10
  30. package/lib/engine/engine_context.js.map +1 -1
  31. package/lib/engine/engine_utils.js +1 -1
  32. package/lib/engine/engine_utils.js.map +1 -1
  33. package/lib/engine-components/AudioSource.d.ts +1 -1
  34. package/lib/engine-components/AudioSource.js +5 -4
  35. package/lib/engine-components/AudioSource.js.map +1 -1
  36. package/lib/engine-components/ReflectionProbe.d.ts +2 -1
  37. package/lib/engine-components/ReflectionProbe.js +4 -1
  38. package/lib/engine-components/ReflectionProbe.js.map +1 -1
  39. package/lib/engine-components/Renderer.js +9 -5
  40. package/lib/engine-components/Renderer.js.map +1 -1
  41. package/lib/engine-components/Skybox.d.ts +7 -1
  42. package/lib/engine-components/Skybox.js +30 -9
  43. package/lib/engine-components/Skybox.js.map +1 -1
  44. package/package.json +2 -2
  45. package/plugins/types/userconfig.d.ts +1 -1
  46. package/plugins/vite/asap.js +26 -20
  47. package/plugins/vite/dependency-watcher.js +8 -2
  48. package/plugins/vite/local-files.js +268 -59
  49. package/src/engine/engine_assetdatabase.ts +3 -1
  50. package/src/engine/engine_context.ts +14 -11
  51. package/src/engine/engine_utils.ts +1 -1
  52. package/src/engine-components/AudioSource.ts +5 -5
  53. package/src/engine-components/ReflectionProbe.ts +5 -1
  54. package/src/engine-components/Renderer.ts +10 -7
  55. package/src/engine-components/Skybox.ts +30 -10
@@ -758,6 +758,9 @@ export class Context implements IContext {
758
758
  this.physics?.engine?.clearCaches();
759
759
  this.lodsManager.disable();
760
760
 
761
+ this._onBeforeRenderListeners.clear();
762
+ this._onAfterRenderListeners.clear();
763
+
761
764
  if (!this.isManagedExternally) {
762
765
  if (this.renderer) {
763
766
  this.renderer.renderLists.dispose();
@@ -889,16 +892,17 @@ export class Context implements IContext {
889
892
  }
890
893
  }
891
894
 
892
- private _onBeforeRenderListeners = new Map<string, OnRenderCallback[]>();
893
- private _onAfterRenderListeners = new Map<string, OnRenderCallback[]>();
895
+ private readonly _onBeforeRenderListeners = new Map<string, OnRenderCallback[]>();
896
+ private readonly _onAfterRenderListeners = new Map<string, OnRenderCallback[]>();
894
897
 
895
898
  /** Use to subscribe to onBeforeRender events on threejs objects.
896
899
  * @link https://threejs.org/docs/#api/en/core/Object3D.onBeforeRender
897
900
  */
898
901
  addBeforeRenderListener(target: Object3D, callback: OnRenderCallback) {
899
902
  if (!this._onBeforeRenderListeners.has(target.uuid)) {
900
- this._onBeforeRenderListeners.set(target.uuid, []);
901
- target.onBeforeRender = this._createRenderCallbackWrapper(target, this._onBeforeRenderListeners);
903
+ const arr: OnRenderCallback[] = [];
904
+ this._onBeforeRenderListeners.set(target.uuid, arr);
905
+ target.onBeforeRender = this._createRenderCallbackWrapper(arr);
902
906
  }
903
907
  this._onBeforeRenderListeners.get(target.uuid)!.push(callback);
904
908
  }
@@ -919,8 +923,9 @@ export class Context implements IContext {
919
923
  */
920
924
  addAfterRenderListener(target: Object3D, callback: OnRenderCallback) {
921
925
  if (!this._onAfterRenderListeners.has(target.uuid)) {
922
- this._onAfterRenderListeners.set(target.uuid, []);
923
- target.onAfterRender = this._createRenderCallbackWrapper(target, this._onAfterRenderListeners);
926
+ const arr = [];
927
+ this._onAfterRenderListeners.set(target.uuid, arr);
928
+ target.onAfterRender = this._createRenderCallbackWrapper(arr);
924
929
  }
925
930
  this._onAfterRenderListeners.get(target.uuid)?.push(callback);
926
931
  }
@@ -937,12 +942,10 @@ export class Context implements IContext {
937
942
  }
938
943
 
939
944
 
940
- private _createRenderCallbackWrapper(target: Object3D, array: Map<string, OnRenderCallback[]>): OnRenderCallback {
945
+ private _createRenderCallbackWrapper(array: OnRenderCallback[]): OnRenderCallback {
941
946
  return (renderer, scene, camera, geometry, material, group) => {
942
- const arr = array.get(target.uuid);
943
- if (!arr) return;
944
- for (let i = 0; i < arr.length; i++) {
945
- const fn = arr[i];
947
+ for (let i = 0; i < array.length; i++) {
948
+ const fn = array[i];
946
949
  fn(renderer, scene, camera, geometry, material, group);
947
950
  }
948
951
  }
@@ -905,7 +905,7 @@ export async function generateQRCode(args: { domElement?: HTMLElement, text: str
905
905
 
906
906
  // Ensure that the QRCode library is loaded
907
907
  if (!globalThis["QRCode"]) {
908
- const url = "https://cdn.rawgit.com/davidshimjs/qrcodejs/gh-pages/qrcode.min.js";
908
+ const url = "https://cdn.jsdelivr.net/gh/davidshimjs/qrcodejs@gh-pages/qrcode.min.js";
909
909
  let script = document.head.querySelector(`script[src="${url}"]`) as HTMLScriptElement;
910
910
  if (!script) {
911
911
  script = document.createElement("script");
@@ -96,10 +96,10 @@ export class AudioSource extends Behaviour {
96
96
  /**
97
97
  * When true, the audio clip will be loaded during initialization rather than when play() is called.
98
98
  * This can reduce playback delay but increases initial loading time.
99
- * @default false
99
+ * @default true
100
100
  */
101
101
  @serializable()
102
- preload: boolean = false;
102
+ preload: boolean = true;
103
103
 
104
104
  /**
105
105
  * When true, audio will continue playing when the browser tab loses focus.
@@ -347,7 +347,8 @@ export class AudioSource extends Behaviour {
347
347
 
348
348
  /** @internal */
349
349
  awake() {
350
- if (debug) console.log(this);
350
+ if (debug) console.log("[AudioSource]", this);
351
+
351
352
  this.audioLoader = new AudioLoader();
352
353
  if (this.playOnAwake) this.shouldPlay = true;
353
354
 
@@ -431,7 +432,6 @@ export class AudioSource extends Behaviour {
431
432
  if (this.context.application.muted) sound.setVolume(0);
432
433
  else sound.setVolume(this.volume);
433
434
  sound.autoplay = this.shouldPlay && AudioSource.userInteractionRegistered;
434
-
435
435
  this.applySpatialDistanceSettings();
436
436
 
437
437
  if (sound.isPlaying)
@@ -509,7 +509,7 @@ export class AudioSource extends Behaviour {
509
509
  console.log("load audio", clip);
510
510
  const buffer = await this.audioLoader.loadAsync(clip).catch(console.error);
511
511
  if(this.destroyed) return;
512
- this._lastClipStartedLoading = null;
512
+ if(this._lastClipStartedLoading === clip) this._lastClipStartedLoading = null;
513
513
  if (buffer) this.createAudio(buffer);
514
514
  }
515
515
  else console.warn("Unsupported audio clip type", clip)
@@ -22,6 +22,10 @@ export class ReflectionProbe extends Behaviour {
22
22
 
23
23
  private static _probes: Map<Context, ReflectionProbe[]> = new Map();
24
24
 
25
+ static isUsingReflectionProbe(material: Material) {
26
+ return !!(material[$reflectionProbeKey] || material[$originalMaterial]?.[$reflectionProbeKey]);
27
+ }
28
+
25
29
  public static get(object: Object3D | null | undefined, context: Context, isAnchor: boolean, anchor?: Object3D): ReflectionProbe | null {
26
30
  if (!object || object.isObject3D !== true) return null;
27
31
  if (disable) return null;
@@ -29,7 +33,7 @@ export class ReflectionProbe extends Behaviour {
29
33
  if (probes) {
30
34
  for (const probe of probes) {
31
35
  if (!probe.__didAwake) probe.__internalAwake();
32
- if (probe.enabled) {
36
+ if (probe.activeAndEnabled) {
33
37
  if (anchor) {
34
38
  // test if anchor is reflection probe object
35
39
  if (probe.gameObject === anchor) {
@@ -708,7 +708,15 @@ export class Renderer extends Behaviour implements IRenderer {
708
708
  if (this.reflectionProbeUsage !== ReflectionProbeUsage.Off && this._reflectionProbe) {
709
709
  this._reflectionProbe.onSet(this);
710
710
  }
711
-
711
+ // since three 163 we need to set the envMap to the scene envMap if it is not set
712
+ // otherwise the envmapIntensity has no effect: https://github.com/mrdoob/three.js/pull/27903
713
+ // internal issue: https://linear.app/needle/issue/NE-6363
714
+ for (const mat of this._sharedMaterials) {
715
+ // If the material has a envMap and is NOT using a reflection probe we set the envMap to the scene environment
716
+ if (mat && "envMap" in mat && "envMapIntensity" in mat && !ReflectionProbe.isUsingReflectionProbe(mat)) {
717
+ mat.envMap = this.context.scene.environment;
718
+ }
719
+ }
712
720
  }
713
721
 
714
722
  private onBeforeRenderThree = (_renderer, _scene, _camera, _geometry, material, _group) => {
@@ -716,11 +724,6 @@ export class Renderer extends Behaviour implements IRenderer {
716
724
  const factor = this.hasLightmap ? Math.PI : 1;
717
725
  const environmentIntensity = this.context.mainCameraComponent?.environmentIntensity ?? 1;
718
726
  material.envMapIntensity = Math.max(0, environmentIntensity * this.context.sceneLighting.environmentIntensity / factor);
719
-
720
- // since three 163 we need to set the envMap to the scene envMap if it is not set
721
- // otherwise the envmapIntensity has no effect: https://github.com/mrdoob/three.js/pull/27903
722
- // internal issue: https://linear.app/needle/issue/NE-6363
723
- if (!material.envMap) material.envMap = this.context.scene.environment;
724
727
  }
725
728
 
726
729
  if (this._lightmaps) {
@@ -856,7 +859,7 @@ export class SkinnedMeshRenderer extends MeshRenderer {
856
859
  mesh.computeBoundingSphere();
857
860
  mesh.geometry = geometry;
858
861
  }
859
- catch(err) {
862
+ catch (err) {
860
863
  console.error(`Error updating bounding sphere for ${mesh.name}`, err);
861
864
  }
862
865
  }
@@ -124,11 +124,17 @@ function registerLoadedTexture(src: string, texture: Promise<Texture>) {
124
124
  * evt.detail.apply(url);
125
125
  * });
126
126
  * ```
127
+ *
128
+ * @example update skybox url
129
+ * ```ts
130
+ * skybox.setSkybox("https://example.com/skybox.hdr");
131
+ * ```
127
132
  */
128
133
  export class RemoteSkybox extends Behaviour {
129
134
 
130
135
  /**
131
- * URL to a remote skybox. This value can also use a magic skybox name. Options are "quicklook", "quicklook-ar", "studio", "blurred-skybox".
136
+ * URL to a remote skybox. This value can also use a magic skybox name. Options are "quicklook", "quicklook-ar", "studio", "blurred-skybox".
137
+ * To update the skybox/environment map use `setSkybox(url)`
132
138
  * @example
133
139
  * ```ts
134
140
  * skybox.url = "https://example.com/skybox.hdr";
@@ -197,6 +203,9 @@ export class RemoteSkybox extends Behaviour {
197
203
  if (this.isRemoteTexture(this.url)) {
198
204
  this.setSkybox(this.url);
199
205
  }
206
+ else if (debug) {
207
+ console.warn(`RemoteSkybox: Not setting skybox: ${this.url} is not a remote texture. If you want to set a local texture, set allowNetworking to false.`);
208
+ }
200
209
  }
201
210
  }
202
211
 
@@ -222,7 +231,7 @@ export class RemoteSkybox extends Behaviour {
222
231
  if (debug) console.log("Set remote skybox url: " + url);
223
232
 
224
233
  if (this._prevUrl === url && this._prevLoadedEnvironment) {
225
- this.applySkybox();
234
+ this.apply();
226
235
  return true;
227
236
  }
228
237
  else {
@@ -231,19 +240,30 @@ export class RemoteSkybox extends Behaviour {
231
240
  }
232
241
  this._prevUrl = url;
233
242
 
234
- const envMap = await this.loadTexture(url, name);
235
- if (!envMap) return false;
243
+ const texture = await this.loadTexture(url, name);
244
+ if (!texture) {
245
+ if (debug) console.warn("RemoteSkybox: Failed to load texture from url", url);
246
+ return false;
247
+ }
236
248
  // Check if we're still enabled
237
- if (!this.enabled) return false;
249
+ if (!this.enabled) {
250
+ if (debug) console.warn("RemoteSkybox: Component is not enabled, aborting setSkybox");
251
+ return false;
252
+ }
253
+ // Check if the url has changed while loading
254
+ if (this._prevUrl !== url) {
255
+ if (debug) console.warn("RemoteSkybox: URL changed while loading texture, aborting setSkybox");
256
+ return false; // URL changed while loading
257
+ }
238
258
  // Update the current url
239
259
  this.url = url;
240
260
  const nameIndex = url.lastIndexOf("/");
241
- envMap.name = url.substring(nameIndex >= 0 ? nameIndex + 1 : 0);
261
+ texture.name = url.substring(nameIndex >= 0 ? nameIndex + 1 : 0);
242
262
  if (this._loader instanceof TextureLoader) {
243
- envMap.colorSpace = SRGBColorSpace;
263
+ texture.colorSpace = SRGBColorSpace;
244
264
  }
245
- this._prevLoadedEnvironment = envMap;
246
- this.applySkybox();
265
+ this._prevLoadedEnvironment = texture;
266
+ this.apply();
247
267
  return true;
248
268
  }
249
269
 
@@ -284,7 +304,7 @@ export class RemoteSkybox extends Behaviour {
284
304
  return envMap;
285
305
  }
286
306
 
287
- private applySkybox() {
307
+ private apply() {
288
308
  const envMap = this._prevLoadedEnvironment;
289
309
  if (!envMap) return;
290
310